@damienmortini/three 0.1.181 → 0.1.182
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.
|
@@ -53,7 +53,6 @@ import {
|
|
|
53
53
|
SkinnedMesh,
|
|
54
54
|
Sphere,
|
|
55
55
|
SpotLight,
|
|
56
|
-
TangentSpaceNormalMap,
|
|
57
56
|
Texture,
|
|
58
57
|
TextureLoader,
|
|
59
58
|
TriangleFanDrawMode,
|
|
@@ -63,6 +62,7 @@ import {
|
|
|
63
62
|
VectorKeyframeTrack,
|
|
64
63
|
sRGBEncoding
|
|
65
64
|
} from '../../../../three/src/Three.js';
|
|
65
|
+
import { toTrianglesDrawMode } from '../utils/BufferGeometryUtils.js';
|
|
66
66
|
|
|
67
67
|
class GLTFLoader extends Loader {
|
|
68
68
|
|
|
@@ -287,6 +287,7 @@ class GLTFLoader extends Loader {
|
|
|
287
287
|
let json;
|
|
288
288
|
const extensions = {};
|
|
289
289
|
const plugins = {};
|
|
290
|
+
const textDecoder = new TextDecoder();
|
|
290
291
|
|
|
291
292
|
if ( typeof data === 'string' ) {
|
|
292
293
|
|
|
@@ -294,7 +295,7 @@ class GLTFLoader extends Loader {
|
|
|
294
295
|
|
|
295
296
|
} else if ( data instanceof ArrayBuffer ) {
|
|
296
297
|
|
|
297
|
-
const magic =
|
|
298
|
+
const magic = textDecoder.decode( new Uint8Array( data, 0, 4 ) );
|
|
298
299
|
|
|
299
300
|
if ( magic === BINARY_EXTENSION_HEADER_MAGIC ) {
|
|
300
301
|
|
|
@@ -313,7 +314,7 @@ class GLTFLoader extends Loader {
|
|
|
313
314
|
|
|
314
315
|
} else {
|
|
315
316
|
|
|
316
|
-
json = JSON.parse(
|
|
317
|
+
json = JSON.parse( textDecoder.decode( data ) );
|
|
317
318
|
|
|
318
319
|
}
|
|
319
320
|
|
|
@@ -369,10 +370,6 @@ class GLTFLoader extends Loader {
|
|
|
369
370
|
extensions[ extensionName ] = new GLTFMaterialsUnlitExtension();
|
|
370
371
|
break;
|
|
371
372
|
|
|
372
|
-
case EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS:
|
|
373
|
-
extensions[ extensionName ] = new GLTFMaterialsPbrSpecularGlossinessExtension();
|
|
374
|
-
break;
|
|
375
|
-
|
|
376
373
|
case EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:
|
|
377
374
|
extensions[ extensionName ] = new GLTFDracoMeshCompressionExtension( json, this.dracoLoader );
|
|
378
375
|
break;
|
|
@@ -465,7 +462,6 @@ const EXTENSIONS = {
|
|
|
465
462
|
KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',
|
|
466
463
|
KHR_MATERIALS_CLEARCOAT: 'KHR_materials_clearcoat',
|
|
467
464
|
KHR_MATERIALS_IOR: 'KHR_materials_ior',
|
|
468
|
-
KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
|
|
469
465
|
KHR_MATERIALS_SHEEN: 'KHR_materials_sheen',
|
|
470
466
|
KHR_MATERIALS_SPECULAR: 'KHR_materials_specular',
|
|
471
467
|
KHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission',
|
|
@@ -576,6 +572,8 @@ class GLTFLightsExtension {
|
|
|
576
572
|
|
|
577
573
|
lightNode.decay = 2;
|
|
578
574
|
|
|
575
|
+
assignExtrasToUserData( lightNode, lightDef );
|
|
576
|
+
|
|
579
577
|
if ( lightDef.intensity !== undefined ) lightNode.intensity = lightDef.intensity;
|
|
580
578
|
|
|
581
579
|
lightNode.name = parser.createUniqueName( lightDef.name || ( 'light_' + lightIndex ) );
|
|
@@ -588,6 +586,14 @@ class GLTFLightsExtension {
|
|
|
588
586
|
|
|
589
587
|
}
|
|
590
588
|
|
|
589
|
+
getDependency( type, index ) {
|
|
590
|
+
|
|
591
|
+
if ( type !== 'light' ) return;
|
|
592
|
+
|
|
593
|
+
return this._loadLight( index );
|
|
594
|
+
|
|
595
|
+
}
|
|
596
|
+
|
|
591
597
|
createNodeAttachment( nodeIndex ) {
|
|
592
598
|
|
|
593
599
|
const self = this;
|
|
@@ -1562,9 +1568,10 @@ class GLTFBinaryExtension {
|
|
|
1562
1568
|
this.body = null;
|
|
1563
1569
|
|
|
1564
1570
|
const headerView = new DataView( data, 0, BINARY_EXTENSION_HEADER_LENGTH );
|
|
1571
|
+
const textDecoder = new TextDecoder();
|
|
1565
1572
|
|
|
1566
1573
|
this.header = {
|
|
1567
|
-
magic:
|
|
1574
|
+
magic: textDecoder.decode( new Uint8Array( data.slice( 0, 4 ) ) ),
|
|
1568
1575
|
version: headerView.getUint32( 4, true ),
|
|
1569
1576
|
length: headerView.getUint32( 8, true )
|
|
1570
1577
|
};
|
|
@@ -1594,7 +1601,7 @@ class GLTFBinaryExtension {
|
|
|
1594
1601
|
if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.JSON ) {
|
|
1595
1602
|
|
|
1596
1603
|
const contentArray = new Uint8Array( data, BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength );
|
|
1597
|
-
this.content =
|
|
1604
|
+
this.content = textDecoder.decode( contentArray );
|
|
1598
1605
|
|
|
1599
1606
|
} else if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.BIN ) {
|
|
1600
1607
|
|
|
@@ -1758,335 +1765,6 @@ class GLTFTextureTransformExtension {
|
|
|
1758
1765
|
|
|
1759
1766
|
}
|
|
1760
1767
|
|
|
1761
|
-
/**
|
|
1762
|
-
* Specular-Glossiness Extension
|
|
1763
|
-
*
|
|
1764
|
-
* Specification: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Archived/KHR_materials_pbrSpecularGlossiness
|
|
1765
|
-
*/
|
|
1766
|
-
|
|
1767
|
-
/**
|
|
1768
|
-
* A sub class of StandardMaterial with some of the functionality
|
|
1769
|
-
* changed via the `onBeforeCompile` callback
|
|
1770
|
-
* @pailhead
|
|
1771
|
-
*/
|
|
1772
|
-
class GLTFMeshStandardSGMaterial extends MeshStandardMaterial {
|
|
1773
|
-
|
|
1774
|
-
constructor( params ) {
|
|
1775
|
-
|
|
1776
|
-
super();
|
|
1777
|
-
|
|
1778
|
-
this.isGLTFSpecularGlossinessMaterial = true;
|
|
1779
|
-
|
|
1780
|
-
//various chunks that need replacing
|
|
1781
|
-
const specularMapParsFragmentChunk = [
|
|
1782
|
-
'#ifdef USE_SPECULARMAP',
|
|
1783
|
-
' uniform sampler2D specularMap;',
|
|
1784
|
-
'#endif'
|
|
1785
|
-
].join( '\n' );
|
|
1786
|
-
|
|
1787
|
-
const glossinessMapParsFragmentChunk = [
|
|
1788
|
-
'#ifdef USE_GLOSSINESSMAP',
|
|
1789
|
-
' uniform sampler2D glossinessMap;',
|
|
1790
|
-
'#endif'
|
|
1791
|
-
].join( '\n' );
|
|
1792
|
-
|
|
1793
|
-
const specularMapFragmentChunk = [
|
|
1794
|
-
'vec3 specularFactor = specular;',
|
|
1795
|
-
'#ifdef USE_SPECULARMAP',
|
|
1796
|
-
' vec4 texelSpecular = texture2D( specularMap, vUv );',
|
|
1797
|
-
' // reads channel RGB, compatible with a glTF Specular-Glossiness (RGBA) texture',
|
|
1798
|
-
' specularFactor *= texelSpecular.rgb;',
|
|
1799
|
-
'#endif'
|
|
1800
|
-
].join( '\n' );
|
|
1801
|
-
|
|
1802
|
-
const glossinessMapFragmentChunk = [
|
|
1803
|
-
'float glossinessFactor = glossiness;',
|
|
1804
|
-
'#ifdef USE_GLOSSINESSMAP',
|
|
1805
|
-
' vec4 texelGlossiness = texture2D( glossinessMap, vUv );',
|
|
1806
|
-
' // reads channel A, compatible with a glTF Specular-Glossiness (RGBA) texture',
|
|
1807
|
-
' glossinessFactor *= texelGlossiness.a;',
|
|
1808
|
-
'#endif'
|
|
1809
|
-
].join( '\n' );
|
|
1810
|
-
|
|
1811
|
-
const lightPhysicalFragmentChunk = [
|
|
1812
|
-
'PhysicalMaterial material;',
|
|
1813
|
-
'material.diffuseColor = diffuseColor.rgb * ( 1. - max( specularFactor.r, max( specularFactor.g, specularFactor.b ) ) );',
|
|
1814
|
-
'vec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );',
|
|
1815
|
-
'float geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );',
|
|
1816
|
-
'material.roughness = max( 1.0 - glossinessFactor, 0.0525 ); // 0.0525 corresponds to the base mip of a 256 cubemap.',
|
|
1817
|
-
'material.roughness += geometryRoughness;',
|
|
1818
|
-
'material.roughness = min( material.roughness, 1.0 );',
|
|
1819
|
-
'material.specularColor = specularFactor;',
|
|
1820
|
-
].join( '\n' );
|
|
1821
|
-
|
|
1822
|
-
const uniforms = {
|
|
1823
|
-
specular: { value: new Color().setHex( 0xffffff ) },
|
|
1824
|
-
glossiness: { value: 1 },
|
|
1825
|
-
specularMap: { value: null },
|
|
1826
|
-
glossinessMap: { value: null }
|
|
1827
|
-
};
|
|
1828
|
-
|
|
1829
|
-
this._extraUniforms = uniforms;
|
|
1830
|
-
|
|
1831
|
-
this.onBeforeCompile = function ( shader ) {
|
|
1832
|
-
|
|
1833
|
-
for ( const uniformName in uniforms ) {
|
|
1834
|
-
|
|
1835
|
-
shader.uniforms[ uniformName ] = uniforms[ uniformName ];
|
|
1836
|
-
|
|
1837
|
-
}
|
|
1838
|
-
|
|
1839
|
-
shader.fragmentShader = shader.fragmentShader
|
|
1840
|
-
.replace( 'uniform float roughness;', 'uniform vec3 specular;' )
|
|
1841
|
-
.replace( 'uniform float metalness;', 'uniform float glossiness;' )
|
|
1842
|
-
.replace( '#include <roughnessmap_pars_fragment>', specularMapParsFragmentChunk )
|
|
1843
|
-
.replace( '#include <metalnessmap_pars_fragment>', glossinessMapParsFragmentChunk )
|
|
1844
|
-
.replace( '#include <roughnessmap_fragment>', specularMapFragmentChunk )
|
|
1845
|
-
.replace( '#include <metalnessmap_fragment>', glossinessMapFragmentChunk )
|
|
1846
|
-
.replace( '#include <lights_physical_fragment>', lightPhysicalFragmentChunk );
|
|
1847
|
-
|
|
1848
|
-
};
|
|
1849
|
-
|
|
1850
|
-
Object.defineProperties( this, {
|
|
1851
|
-
|
|
1852
|
-
specular: {
|
|
1853
|
-
get: function () {
|
|
1854
|
-
|
|
1855
|
-
return uniforms.specular.value;
|
|
1856
|
-
|
|
1857
|
-
},
|
|
1858
|
-
set: function ( v ) {
|
|
1859
|
-
|
|
1860
|
-
uniforms.specular.value = v;
|
|
1861
|
-
|
|
1862
|
-
}
|
|
1863
|
-
},
|
|
1864
|
-
|
|
1865
|
-
specularMap: {
|
|
1866
|
-
get: function () {
|
|
1867
|
-
|
|
1868
|
-
return uniforms.specularMap.value;
|
|
1869
|
-
|
|
1870
|
-
},
|
|
1871
|
-
set: function ( v ) {
|
|
1872
|
-
|
|
1873
|
-
uniforms.specularMap.value = v;
|
|
1874
|
-
|
|
1875
|
-
if ( v ) {
|
|
1876
|
-
|
|
1877
|
-
this.defines.USE_SPECULARMAP = ''; // USE_UV is set by the renderer for specular maps
|
|
1878
|
-
|
|
1879
|
-
} else {
|
|
1880
|
-
|
|
1881
|
-
delete this.defines.USE_SPECULARMAP;
|
|
1882
|
-
|
|
1883
|
-
}
|
|
1884
|
-
|
|
1885
|
-
}
|
|
1886
|
-
},
|
|
1887
|
-
|
|
1888
|
-
glossiness: {
|
|
1889
|
-
get: function () {
|
|
1890
|
-
|
|
1891
|
-
return uniforms.glossiness.value;
|
|
1892
|
-
|
|
1893
|
-
},
|
|
1894
|
-
set: function ( v ) {
|
|
1895
|
-
|
|
1896
|
-
uniforms.glossiness.value = v;
|
|
1897
|
-
|
|
1898
|
-
}
|
|
1899
|
-
},
|
|
1900
|
-
|
|
1901
|
-
glossinessMap: {
|
|
1902
|
-
get: function () {
|
|
1903
|
-
|
|
1904
|
-
return uniforms.glossinessMap.value;
|
|
1905
|
-
|
|
1906
|
-
},
|
|
1907
|
-
set: function ( v ) {
|
|
1908
|
-
|
|
1909
|
-
uniforms.glossinessMap.value = v;
|
|
1910
|
-
|
|
1911
|
-
if ( v ) {
|
|
1912
|
-
|
|
1913
|
-
this.defines.USE_GLOSSINESSMAP = '';
|
|
1914
|
-
this.defines.USE_UV = '';
|
|
1915
|
-
|
|
1916
|
-
} else {
|
|
1917
|
-
|
|
1918
|
-
delete this.defines.USE_GLOSSINESSMAP;
|
|
1919
|
-
delete this.defines.USE_UV;
|
|
1920
|
-
|
|
1921
|
-
}
|
|
1922
|
-
|
|
1923
|
-
}
|
|
1924
|
-
}
|
|
1925
|
-
|
|
1926
|
-
} );
|
|
1927
|
-
|
|
1928
|
-
delete this.metalness;
|
|
1929
|
-
delete this.roughness;
|
|
1930
|
-
delete this.metalnessMap;
|
|
1931
|
-
delete this.roughnessMap;
|
|
1932
|
-
|
|
1933
|
-
this.setValues( params );
|
|
1934
|
-
|
|
1935
|
-
}
|
|
1936
|
-
|
|
1937
|
-
copy( source ) {
|
|
1938
|
-
|
|
1939
|
-
super.copy( source );
|
|
1940
|
-
|
|
1941
|
-
this.specularMap = source.specularMap;
|
|
1942
|
-
this.specular.copy( source.specular );
|
|
1943
|
-
this.glossinessMap = source.glossinessMap;
|
|
1944
|
-
this.glossiness = source.glossiness;
|
|
1945
|
-
delete this.metalness;
|
|
1946
|
-
delete this.roughness;
|
|
1947
|
-
delete this.metalnessMap;
|
|
1948
|
-
delete this.roughnessMap;
|
|
1949
|
-
return this;
|
|
1950
|
-
|
|
1951
|
-
}
|
|
1952
|
-
|
|
1953
|
-
}
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
class GLTFMaterialsPbrSpecularGlossinessExtension {
|
|
1957
|
-
|
|
1958
|
-
constructor() {
|
|
1959
|
-
|
|
1960
|
-
this.name = EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS;
|
|
1961
|
-
|
|
1962
|
-
this.specularGlossinessParams = [
|
|
1963
|
-
'color',
|
|
1964
|
-
'map',
|
|
1965
|
-
'lightMap',
|
|
1966
|
-
'lightMapIntensity',
|
|
1967
|
-
'aoMap',
|
|
1968
|
-
'aoMapIntensity',
|
|
1969
|
-
'emissive',
|
|
1970
|
-
'emissiveIntensity',
|
|
1971
|
-
'emissiveMap',
|
|
1972
|
-
'bumpMap',
|
|
1973
|
-
'bumpScale',
|
|
1974
|
-
'normalMap',
|
|
1975
|
-
'normalMapType',
|
|
1976
|
-
'displacementMap',
|
|
1977
|
-
'displacementScale',
|
|
1978
|
-
'displacementBias',
|
|
1979
|
-
'specularMap',
|
|
1980
|
-
'specular',
|
|
1981
|
-
'glossinessMap',
|
|
1982
|
-
'glossiness',
|
|
1983
|
-
'alphaMap',
|
|
1984
|
-
'envMap',
|
|
1985
|
-
'envMapIntensity'
|
|
1986
|
-
];
|
|
1987
|
-
|
|
1988
|
-
}
|
|
1989
|
-
|
|
1990
|
-
getMaterialType() {
|
|
1991
|
-
|
|
1992
|
-
return GLTFMeshStandardSGMaterial;
|
|
1993
|
-
|
|
1994
|
-
}
|
|
1995
|
-
|
|
1996
|
-
extendParams( materialParams, materialDef, parser ) {
|
|
1997
|
-
|
|
1998
|
-
const pbrSpecularGlossiness = materialDef.extensions[ this.name ];
|
|
1999
|
-
|
|
2000
|
-
materialParams.color = new Color( 1.0, 1.0, 1.0 );
|
|
2001
|
-
materialParams.opacity = 1.0;
|
|
2002
|
-
|
|
2003
|
-
const pending = [];
|
|
2004
|
-
|
|
2005
|
-
if ( Array.isArray( pbrSpecularGlossiness.diffuseFactor ) ) {
|
|
2006
|
-
|
|
2007
|
-
const array = pbrSpecularGlossiness.diffuseFactor;
|
|
2008
|
-
|
|
2009
|
-
materialParams.color.fromArray( array );
|
|
2010
|
-
materialParams.opacity = array[ 3 ];
|
|
2011
|
-
|
|
2012
|
-
}
|
|
2013
|
-
|
|
2014
|
-
if ( pbrSpecularGlossiness.diffuseTexture !== undefined ) {
|
|
2015
|
-
|
|
2016
|
-
pending.push( parser.assignTexture( materialParams, 'map', pbrSpecularGlossiness.diffuseTexture, sRGBEncoding ) );
|
|
2017
|
-
|
|
2018
|
-
}
|
|
2019
|
-
|
|
2020
|
-
materialParams.emissive = new Color( 0.0, 0.0, 0.0 );
|
|
2021
|
-
materialParams.glossiness = pbrSpecularGlossiness.glossinessFactor !== undefined ? pbrSpecularGlossiness.glossinessFactor : 1.0;
|
|
2022
|
-
materialParams.specular = new Color( 1.0, 1.0, 1.0 );
|
|
2023
|
-
|
|
2024
|
-
if ( Array.isArray( pbrSpecularGlossiness.specularFactor ) ) {
|
|
2025
|
-
|
|
2026
|
-
materialParams.specular.fromArray( pbrSpecularGlossiness.specularFactor );
|
|
2027
|
-
|
|
2028
|
-
}
|
|
2029
|
-
|
|
2030
|
-
if ( pbrSpecularGlossiness.specularGlossinessTexture !== undefined ) {
|
|
2031
|
-
|
|
2032
|
-
const specGlossMapDef = pbrSpecularGlossiness.specularGlossinessTexture;
|
|
2033
|
-
pending.push( parser.assignTexture( materialParams, 'glossinessMap', specGlossMapDef ) );
|
|
2034
|
-
pending.push( parser.assignTexture( materialParams, 'specularMap', specGlossMapDef, sRGBEncoding ) );
|
|
2035
|
-
|
|
2036
|
-
}
|
|
2037
|
-
|
|
2038
|
-
return Promise.all( pending );
|
|
2039
|
-
|
|
2040
|
-
}
|
|
2041
|
-
|
|
2042
|
-
createMaterial( materialParams ) {
|
|
2043
|
-
|
|
2044
|
-
const material = new GLTFMeshStandardSGMaterial( materialParams );
|
|
2045
|
-
material.fog = true;
|
|
2046
|
-
|
|
2047
|
-
material.color = materialParams.color;
|
|
2048
|
-
|
|
2049
|
-
material.map = materialParams.map === undefined ? null : materialParams.map;
|
|
2050
|
-
|
|
2051
|
-
material.lightMap = null;
|
|
2052
|
-
material.lightMapIntensity = 1.0;
|
|
2053
|
-
|
|
2054
|
-
material.aoMap = materialParams.aoMap === undefined ? null : materialParams.aoMap;
|
|
2055
|
-
material.aoMapIntensity = 1.0;
|
|
2056
|
-
|
|
2057
|
-
material.emissive = materialParams.emissive;
|
|
2058
|
-
material.emissiveIntensity = materialParams.emissiveIntensity === undefined ? 1.0 : materialParams.emissiveIntensity;
|
|
2059
|
-
material.emissiveMap = materialParams.emissiveMap === undefined ? null : materialParams.emissiveMap;
|
|
2060
|
-
|
|
2061
|
-
material.bumpMap = materialParams.bumpMap === undefined ? null : materialParams.bumpMap;
|
|
2062
|
-
material.bumpScale = 1;
|
|
2063
|
-
|
|
2064
|
-
material.normalMap = materialParams.normalMap === undefined ? null : materialParams.normalMap;
|
|
2065
|
-
material.normalMapType = TangentSpaceNormalMap;
|
|
2066
|
-
|
|
2067
|
-
if ( materialParams.normalScale ) material.normalScale = materialParams.normalScale;
|
|
2068
|
-
|
|
2069
|
-
material.displacementMap = null;
|
|
2070
|
-
material.displacementScale = 1;
|
|
2071
|
-
material.displacementBias = 0;
|
|
2072
|
-
|
|
2073
|
-
material.specularMap = materialParams.specularMap === undefined ? null : materialParams.specularMap;
|
|
2074
|
-
material.specular = materialParams.specular;
|
|
2075
|
-
|
|
2076
|
-
material.glossinessMap = materialParams.glossinessMap === undefined ? null : materialParams.glossinessMap;
|
|
2077
|
-
material.glossiness = materialParams.glossiness;
|
|
2078
|
-
|
|
2079
|
-
material.alphaMap = null;
|
|
2080
|
-
|
|
2081
|
-
material.envMap = materialParams.envMap === undefined ? null : materialParams.envMap;
|
|
2082
|
-
material.envMapIntensity = 1.0;
|
|
2083
|
-
|
|
2084
|
-
return material;
|
|
2085
|
-
|
|
2086
|
-
}
|
|
2087
|
-
|
|
2088
|
-
}
|
|
2089
|
-
|
|
2090
1768
|
/**
|
|
2091
1769
|
* Mesh Quantization Extension
|
|
2092
1770
|
*
|
|
@@ -2554,6 +2232,8 @@ function getImageURIMimeType( uri ) {
|
|
|
2554
2232
|
|
|
2555
2233
|
}
|
|
2556
2234
|
|
|
2235
|
+
const _identityMatrix = new Matrix4();
|
|
2236
|
+
|
|
2557
2237
|
/* GLTF PARSER */
|
|
2558
2238
|
|
|
2559
2239
|
class GLTFParser {
|
|
@@ -2588,9 +2268,17 @@ class GLTFParser {
|
|
|
2588
2268
|
// Use an ImageBitmapLoader if imageBitmaps are supported. Moves much of the
|
|
2589
2269
|
// expensive work of uploading a texture to the GPU off the main thread.
|
|
2590
2270
|
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2271
|
+
let isSafari = false;
|
|
2272
|
+
let isFirefox = false;
|
|
2273
|
+
let firefoxVersion = - 1;
|
|
2274
|
+
|
|
2275
|
+
if ( typeof navigator !== 'undefined' ) {
|
|
2276
|
+
|
|
2277
|
+
isSafari = /^((?!chrome|android).)*safari/i.test( navigator.userAgent ) === true;
|
|
2278
|
+
isFirefox = navigator.userAgent.indexOf( 'Firefox' ) > - 1;
|
|
2279
|
+
firefoxVersion = isFirefox ? navigator.userAgent.match( /Firefox\/([0-9]+)\./ )[ 1 ] : - 1;
|
|
2280
|
+
|
|
2281
|
+
}
|
|
2594
2282
|
|
|
2595
2283
|
if ( typeof createImageBitmap === 'undefined' || isSafari || ( isFirefox && firefoxVersion < 98 ) ) {
|
|
2596
2284
|
|
|
@@ -2855,7 +2543,11 @@ class GLTFParser {
|
|
|
2855
2543
|
break;
|
|
2856
2544
|
|
|
2857
2545
|
case 'node':
|
|
2858
|
-
dependency = this.
|
|
2546
|
+
dependency = this._invokeOne( function ( ext ) {
|
|
2547
|
+
|
|
2548
|
+
return ext.loadNode && ext.loadNode( index );
|
|
2549
|
+
|
|
2550
|
+
} );
|
|
2859
2551
|
break;
|
|
2860
2552
|
|
|
2861
2553
|
case 'mesh':
|
|
@@ -2915,7 +2607,19 @@ class GLTFParser {
|
|
|
2915
2607
|
break;
|
|
2916
2608
|
|
|
2917
2609
|
default:
|
|
2918
|
-
|
|
2610
|
+
dependency = this._invokeOne( function ( ext ) {
|
|
2611
|
+
|
|
2612
|
+
return ext != this && ext.getDependency && ext.getDependency( type, index );
|
|
2613
|
+
|
|
2614
|
+
} );
|
|
2615
|
+
|
|
2616
|
+
if ( ! dependency ) {
|
|
2617
|
+
|
|
2618
|
+
throw new Error( 'Unknown type: ' + type );
|
|
2619
|
+
|
|
2620
|
+
}
|
|
2621
|
+
|
|
2622
|
+
break;
|
|
2919
2623
|
|
|
2920
2624
|
}
|
|
2921
2625
|
|
|
@@ -3025,10 +2729,12 @@ class GLTFParser {
|
|
|
3025
2729
|
|
|
3026
2730
|
if ( accessorDef.bufferView === undefined && accessorDef.sparse === undefined ) {
|
|
3027
2731
|
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
2732
|
+
const itemSize = WEBGL_TYPE_SIZES[ accessorDef.type ];
|
|
2733
|
+
const TypedArray = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];
|
|
2734
|
+
const normalized = accessorDef.normalized === true;
|
|
2735
|
+
|
|
2736
|
+
const array = new TypedArray( accessorDef.count * itemSize );
|
|
2737
|
+
return Promise.resolve( new BufferAttribute( array, itemSize, normalized ) );
|
|
3032
2738
|
|
|
3033
2739
|
}
|
|
3034
2740
|
|
|
@@ -3146,7 +2852,7 @@ class GLTFParser {
|
|
|
3146
2852
|
/**
|
|
3147
2853
|
* Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#textures
|
|
3148
2854
|
* @param {number} textureIndex
|
|
3149
|
-
* @return {Promise<THREE.Texture>}
|
|
2855
|
+
* @return {Promise<THREE.Texture|null>}
|
|
3150
2856
|
*/
|
|
3151
2857
|
loadTexture( textureIndex ) {
|
|
3152
2858
|
|
|
@@ -3316,6 +3022,8 @@ class GLTFParser {
|
|
|
3316
3022
|
|
|
3317
3023
|
return this.getDependency( 'texture', mapDef.index ).then( function ( texture ) {
|
|
3318
3024
|
|
|
3025
|
+
if ( ! texture ) return null;
|
|
3026
|
+
|
|
3319
3027
|
// Materials sample aoMap from UV set 1 and other maps from UV set 0 - this can't be configured
|
|
3320
3028
|
// However, we will copy UV set 0 to UV set 1 on demand for aoMap
|
|
3321
3029
|
if ( mapDef.texCoord !== undefined && mapDef.texCoord != 0 && ! ( mapName === 'aoMap' && mapDef.texCoord == 1 ) ) {
|
|
@@ -3414,7 +3122,6 @@ class GLTFParser {
|
|
|
3414
3122
|
|
|
3415
3123
|
let cacheKey = 'ClonedMaterial:' + material.uuid + ':';
|
|
3416
3124
|
|
|
3417
|
-
if ( material.isGLTFSpecularGlossinessMaterial ) cacheKey += 'specular-glossiness:';
|
|
3418
3125
|
if ( useDerivativeTangents ) cacheKey += 'derivative-tangents:';
|
|
3419
3126
|
if ( useVertexColors ) cacheKey += 'vertex-colors:';
|
|
3420
3127
|
if ( useFlatShading ) cacheKey += 'flat-shading:';
|
|
@@ -3482,13 +3189,7 @@ class GLTFParser {
|
|
|
3482
3189
|
|
|
3483
3190
|
const pending = [];
|
|
3484
3191
|
|
|
3485
|
-
if ( materialExtensions[ EXTENSIONS.
|
|
3486
|
-
|
|
3487
|
-
const sgExtension = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ];
|
|
3488
|
-
materialType = sgExtension.getMaterialType();
|
|
3489
|
-
pending.push( sgExtension.extendParams( materialParams, materialDef, parser ) );
|
|
3490
|
-
|
|
3491
|
-
} else if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ] ) {
|
|
3192
|
+
if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ] ) {
|
|
3492
3193
|
|
|
3493
3194
|
const kmuExtension = extensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ];
|
|
3494
3195
|
materialType = kmuExtension.getMaterialType();
|
|
@@ -3612,17 +3313,7 @@ class GLTFParser {
|
|
|
3612
3313
|
|
|
3613
3314
|
return Promise.all( pending ).then( function () {
|
|
3614
3315
|
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
if ( materialType === GLTFMeshStandardSGMaterial ) {
|
|
3618
|
-
|
|
3619
|
-
material = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].createMaterial( materialParams );
|
|
3620
|
-
|
|
3621
|
-
} else {
|
|
3622
|
-
|
|
3623
|
-
material = new materialType( materialParams );
|
|
3624
|
-
|
|
3625
|
-
}
|
|
3316
|
+
const material = new materialType( materialParams );
|
|
3626
3317
|
|
|
3627
3318
|
if ( materialDef.name ) material.name = materialDef.name;
|
|
3628
3319
|
|
|
@@ -3911,25 +3602,65 @@ class GLTFParser {
|
|
|
3911
3602
|
/**
|
|
3912
3603
|
* Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins
|
|
3913
3604
|
* @param {number} skinIndex
|
|
3914
|
-
* @return {Promise<
|
|
3605
|
+
* @return {Promise<Skeleton>}
|
|
3915
3606
|
*/
|
|
3916
3607
|
loadSkin( skinIndex ) {
|
|
3917
3608
|
|
|
3918
3609
|
const skinDef = this.json.skins[ skinIndex ];
|
|
3919
3610
|
|
|
3920
|
-
const
|
|
3611
|
+
const pending = [];
|
|
3921
3612
|
|
|
3922
|
-
|
|
3613
|
+
for ( let i = 0, il = skinDef.joints.length; i < il; i ++ ) {
|
|
3923
3614
|
|
|
3924
|
-
|
|
3615
|
+
pending.push( this.getDependency( 'node', skinDef.joints[ i ] ) );
|
|
3925
3616
|
|
|
3926
3617
|
}
|
|
3927
3618
|
|
|
3928
|
-
|
|
3619
|
+
if ( skinDef.inverseBindMatrices !== undefined ) {
|
|
3620
|
+
|
|
3621
|
+
pending.push( this.getDependency( 'accessor', skinDef.inverseBindMatrices ) );
|
|
3622
|
+
|
|
3623
|
+
} else {
|
|
3624
|
+
|
|
3625
|
+
pending.push( null );
|
|
3626
|
+
|
|
3627
|
+
}
|
|
3628
|
+
|
|
3629
|
+
return Promise.all( pending ).then( function ( results ) {
|
|
3630
|
+
|
|
3631
|
+
const inverseBindMatrices = results.pop();
|
|
3632
|
+
const jointNodes = results;
|
|
3633
|
+
|
|
3634
|
+
const bones = [];
|
|
3635
|
+
const boneInverses = [];
|
|
3929
3636
|
|
|
3930
|
-
|
|
3637
|
+
for ( let i = 0, il = jointNodes.length; i < il; i ++ ) {
|
|
3638
|
+
|
|
3639
|
+
const jointNode = jointNodes[ i ];
|
|
3640
|
+
|
|
3641
|
+
if ( jointNode ) {
|
|
3642
|
+
|
|
3643
|
+
bones.push( jointNode );
|
|
3644
|
+
|
|
3645
|
+
const mat = new Matrix4();
|
|
3646
|
+
|
|
3647
|
+
if ( inverseBindMatrices !== null ) {
|
|
3648
|
+
|
|
3649
|
+
mat.fromArray( inverseBindMatrices.array, i * 16 );
|
|
3650
|
+
|
|
3651
|
+
}
|
|
3652
|
+
|
|
3653
|
+
boneInverses.push( mat );
|
|
3654
|
+
|
|
3655
|
+
} else {
|
|
3931
3656
|
|
|
3932
|
-
|
|
3657
|
+
console.warn( 'THREE.GLTFLoader: Joint "%s" could not be found.', skinDef.joints[ i ] );
|
|
3658
|
+
|
|
3659
|
+
}
|
|
3660
|
+
|
|
3661
|
+
}
|
|
3662
|
+
|
|
3663
|
+
return new Skeleton( bones, boneInverses );
|
|
3933
3664
|
|
|
3934
3665
|
} );
|
|
3935
3666
|
|
|
@@ -4159,7 +3890,7 @@ class GLTFParser {
|
|
|
4159
3890
|
|
|
4160
3891
|
return ( function () {
|
|
4161
3892
|
|
|
4162
|
-
const
|
|
3893
|
+
const objectPending = [];
|
|
4163
3894
|
|
|
4164
3895
|
const meshPromise = parser._invokeOne( function ( ext ) {
|
|
4165
3896
|
|
|
@@ -4169,13 +3900,13 @@ class GLTFParser {
|
|
|
4169
3900
|
|
|
4170
3901
|
if ( meshPromise ) {
|
|
4171
3902
|
|
|
4172
|
-
|
|
3903
|
+
objectPending.push( meshPromise );
|
|
4173
3904
|
|
|
4174
3905
|
}
|
|
4175
3906
|
|
|
4176
3907
|
if ( nodeDef.camera !== undefined ) {
|
|
4177
3908
|
|
|
4178
|
-
|
|
3909
|
+
objectPending.push( parser.getDependency( 'camera', nodeDef.camera ).then( function ( camera ) {
|
|
4179
3910
|
|
|
4180
3911
|
return parser._getNodeRef( parser.cameraCache, nodeDef.camera, camera );
|
|
4181
3912
|
|
|
@@ -4189,13 +3920,34 @@ class GLTFParser {
|
|
|
4189
3920
|
|
|
4190
3921
|
} ).forEach( function ( promise ) {
|
|
4191
3922
|
|
|
4192
|
-
|
|
3923
|
+
objectPending.push( promise );
|
|
4193
3924
|
|
|
4194
3925
|
} );
|
|
4195
3926
|
|
|
4196
|
-
|
|
3927
|
+
const childPending = [];
|
|
3928
|
+
const childrenDef = nodeDef.children || [];
|
|
3929
|
+
|
|
3930
|
+
for ( let i = 0, il = childrenDef.length; i < il; i ++ ) {
|
|
4197
3931
|
|
|
4198
|
-
|
|
3932
|
+
childPending.push( parser.getDependency( 'node', childrenDef[ i ] ) );
|
|
3933
|
+
|
|
3934
|
+
}
|
|
3935
|
+
|
|
3936
|
+
const skeletonPending = nodeDef.skin === undefined
|
|
3937
|
+
? Promise.resolve( null )
|
|
3938
|
+
: parser.getDependency( 'skin', nodeDef.skin );
|
|
3939
|
+
|
|
3940
|
+
return Promise.all( [
|
|
3941
|
+
Promise.all( objectPending ),
|
|
3942
|
+
Promise.all( childPending ),
|
|
3943
|
+
skeletonPending
|
|
3944
|
+
] );
|
|
3945
|
+
|
|
3946
|
+
}() ).then( function ( results ) {
|
|
3947
|
+
|
|
3948
|
+
const objects = results[ 0 ];
|
|
3949
|
+
const children = results[ 1 ];
|
|
3950
|
+
const skeleton = results[ 2 ];
|
|
4199
3951
|
|
|
4200
3952
|
let node;
|
|
4201
3953
|
|
|
@@ -4275,6 +4027,26 @@ class GLTFParser {
|
|
|
4275
4027
|
|
|
4276
4028
|
parser.associations.get( node ).nodes = nodeIndex;
|
|
4277
4029
|
|
|
4030
|
+
if ( skeleton !== null ) {
|
|
4031
|
+
|
|
4032
|
+
// This full traverse should be fine because
|
|
4033
|
+
// child glTF nodes have not been added to this node yet.
|
|
4034
|
+
node.traverse( function ( mesh ) {
|
|
4035
|
+
|
|
4036
|
+
if ( ! mesh.isSkinnedMesh ) return;
|
|
4037
|
+
|
|
4038
|
+
mesh.bind( skeleton, _identityMatrix );
|
|
4039
|
+
|
|
4040
|
+
} );
|
|
4041
|
+
|
|
4042
|
+
}
|
|
4043
|
+
|
|
4044
|
+
for ( let i = 0, il = children.length; i < il; i ++ ) {
|
|
4045
|
+
|
|
4046
|
+
node.add( children[ i ] );
|
|
4047
|
+
|
|
4048
|
+
}
|
|
4049
|
+
|
|
4278
4050
|
return node;
|
|
4279
4051
|
|
|
4280
4052
|
} );
|
|
@@ -4288,7 +4060,6 @@ class GLTFParser {
|
|
|
4288
4060
|
*/
|
|
4289
4061
|
loadScene( sceneIndex ) {
|
|
4290
4062
|
|
|
4291
|
-
const json = this.json;
|
|
4292
4063
|
const extensions = this.extensions;
|
|
4293
4064
|
const sceneDef = this.json.scenes[ sceneIndex ];
|
|
4294
4065
|
const parser = this;
|
|
@@ -4308,11 +4079,17 @@ class GLTFParser {
|
|
|
4308
4079
|
|
|
4309
4080
|
for ( let i = 0, il = nodeIds.length; i < il; i ++ ) {
|
|
4310
4081
|
|
|
4311
|
-
pending.push(
|
|
4082
|
+
pending.push( parser.getDependency( 'node', nodeIds[ i ] ) );
|
|
4312
4083
|
|
|
4313
4084
|
}
|
|
4314
4085
|
|
|
4315
|
-
return Promise.all( pending ).then( function () {
|
|
4086
|
+
return Promise.all( pending ).then( function ( nodes ) {
|
|
4087
|
+
|
|
4088
|
+
for ( let i = 0, il = nodes.length; i < il; i ++ ) {
|
|
4089
|
+
|
|
4090
|
+
scene.add( nodes[ i ] );
|
|
4091
|
+
|
|
4092
|
+
}
|
|
4316
4093
|
|
|
4317
4094
|
// Removes dangling associations, associations that reference a node that
|
|
4318
4095
|
// didn't make it into the scene.
|
|
@@ -4356,102 +4133,6 @@ class GLTFParser {
|
|
|
4356
4133
|
|
|
4357
4134
|
}
|
|
4358
4135
|
|
|
4359
|
-
function buildNodeHierarchy( nodeId, parentObject, json, parser ) {
|
|
4360
|
-
|
|
4361
|
-
const nodeDef = json.nodes[ nodeId ];
|
|
4362
|
-
|
|
4363
|
-
return parser.getDependency( 'node', nodeId ).then( function ( node ) {
|
|
4364
|
-
|
|
4365
|
-
if ( nodeDef.skin === undefined ) return node;
|
|
4366
|
-
|
|
4367
|
-
// build skeleton here as well
|
|
4368
|
-
|
|
4369
|
-
let skinEntry;
|
|
4370
|
-
|
|
4371
|
-
return parser.getDependency( 'skin', nodeDef.skin ).then( function ( skin ) {
|
|
4372
|
-
|
|
4373
|
-
skinEntry = skin;
|
|
4374
|
-
|
|
4375
|
-
const pendingJoints = [];
|
|
4376
|
-
|
|
4377
|
-
for ( let i = 0, il = skinEntry.joints.length; i < il; i ++ ) {
|
|
4378
|
-
|
|
4379
|
-
pendingJoints.push( parser.getDependency( 'node', skinEntry.joints[ i ] ) );
|
|
4380
|
-
|
|
4381
|
-
}
|
|
4382
|
-
|
|
4383
|
-
return Promise.all( pendingJoints );
|
|
4384
|
-
|
|
4385
|
-
} ).then( function ( jointNodes ) {
|
|
4386
|
-
|
|
4387
|
-
node.traverse( function ( mesh ) {
|
|
4388
|
-
|
|
4389
|
-
if ( ! mesh.isMesh ) return;
|
|
4390
|
-
|
|
4391
|
-
const bones = [];
|
|
4392
|
-
const boneInverses = [];
|
|
4393
|
-
|
|
4394
|
-
for ( let j = 0, jl = jointNodes.length; j < jl; j ++ ) {
|
|
4395
|
-
|
|
4396
|
-
const jointNode = jointNodes[ j ];
|
|
4397
|
-
|
|
4398
|
-
if ( jointNode ) {
|
|
4399
|
-
|
|
4400
|
-
bones.push( jointNode );
|
|
4401
|
-
|
|
4402
|
-
const mat = new Matrix4();
|
|
4403
|
-
|
|
4404
|
-
if ( skinEntry.inverseBindMatrices !== undefined ) {
|
|
4405
|
-
|
|
4406
|
-
mat.fromArray( skinEntry.inverseBindMatrices.array, j * 16 );
|
|
4407
|
-
|
|
4408
|
-
}
|
|
4409
|
-
|
|
4410
|
-
boneInverses.push( mat );
|
|
4411
|
-
|
|
4412
|
-
} else {
|
|
4413
|
-
|
|
4414
|
-
console.warn( 'THREE.GLTFLoader: Joint "%s" could not be found.', skinEntry.joints[ j ] );
|
|
4415
|
-
|
|
4416
|
-
}
|
|
4417
|
-
|
|
4418
|
-
}
|
|
4419
|
-
|
|
4420
|
-
mesh.bind( new Skeleton( bones, boneInverses ), mesh.matrixWorld );
|
|
4421
|
-
|
|
4422
|
-
} );
|
|
4423
|
-
|
|
4424
|
-
return node;
|
|
4425
|
-
|
|
4426
|
-
} );
|
|
4427
|
-
|
|
4428
|
-
} ).then( function ( node ) {
|
|
4429
|
-
|
|
4430
|
-
// build node hierachy
|
|
4431
|
-
|
|
4432
|
-
parentObject.add( node );
|
|
4433
|
-
|
|
4434
|
-
const pending = [];
|
|
4435
|
-
|
|
4436
|
-
if ( nodeDef.children ) {
|
|
4437
|
-
|
|
4438
|
-
const children = nodeDef.children;
|
|
4439
|
-
|
|
4440
|
-
for ( let i = 0, il = children.length; i < il; i ++ ) {
|
|
4441
|
-
|
|
4442
|
-
const child = children[ i ];
|
|
4443
|
-
pending.push( buildNodeHierarchy( child, node, json, parser ) );
|
|
4444
|
-
|
|
4445
|
-
}
|
|
4446
|
-
|
|
4447
|
-
}
|
|
4448
|
-
|
|
4449
|
-
return Promise.all( pending );
|
|
4450
|
-
|
|
4451
|
-
} );
|
|
4452
|
-
|
|
4453
|
-
}
|
|
4454
|
-
|
|
4455
4136
|
/**
|
|
4456
4137
|
* @param {BufferGeometry} geometry
|
|
4457
4138
|
* @param {GLTF.Primitive} primitiveDef
|
|
@@ -4627,98 +4308,4 @@ function addPrimitiveAttributes( geometry, primitiveDef, parser ) {
|
|
|
4627
4308
|
|
|
4628
4309
|
}
|
|
4629
4310
|
|
|
4630
|
-
/**
|
|
4631
|
-
* @param {BufferGeometry} geometry
|
|
4632
|
-
* @param {Number} drawMode
|
|
4633
|
-
* @return {BufferGeometry}
|
|
4634
|
-
*/
|
|
4635
|
-
function toTrianglesDrawMode( geometry, drawMode ) {
|
|
4636
|
-
|
|
4637
|
-
let index = geometry.getIndex();
|
|
4638
|
-
|
|
4639
|
-
// generate index if not present
|
|
4640
|
-
|
|
4641
|
-
if ( index === null ) {
|
|
4642
|
-
|
|
4643
|
-
const indices = [];
|
|
4644
|
-
|
|
4645
|
-
const position = geometry.getAttribute( 'position' );
|
|
4646
|
-
|
|
4647
|
-
if ( position !== undefined ) {
|
|
4648
|
-
|
|
4649
|
-
for ( let i = 0; i < position.count; i ++ ) {
|
|
4650
|
-
|
|
4651
|
-
indices.push( i );
|
|
4652
|
-
|
|
4653
|
-
}
|
|
4654
|
-
|
|
4655
|
-
geometry.setIndex( indices );
|
|
4656
|
-
index = geometry.getIndex();
|
|
4657
|
-
|
|
4658
|
-
} else {
|
|
4659
|
-
|
|
4660
|
-
console.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.' );
|
|
4661
|
-
return geometry;
|
|
4662
|
-
|
|
4663
|
-
}
|
|
4664
|
-
|
|
4665
|
-
}
|
|
4666
|
-
|
|
4667
|
-
//
|
|
4668
|
-
|
|
4669
|
-
const numberOfTriangles = index.count - 2;
|
|
4670
|
-
const newIndices = [];
|
|
4671
|
-
|
|
4672
|
-
if ( drawMode === TriangleFanDrawMode ) {
|
|
4673
|
-
|
|
4674
|
-
// gl.TRIANGLE_FAN
|
|
4675
|
-
|
|
4676
|
-
for ( let i = 1; i <= numberOfTriangles; i ++ ) {
|
|
4677
|
-
|
|
4678
|
-
newIndices.push( index.getX( 0 ) );
|
|
4679
|
-
newIndices.push( index.getX( i ) );
|
|
4680
|
-
newIndices.push( index.getX( i + 1 ) );
|
|
4681
|
-
|
|
4682
|
-
}
|
|
4683
|
-
|
|
4684
|
-
} else {
|
|
4685
|
-
|
|
4686
|
-
// gl.TRIANGLE_STRIP
|
|
4687
|
-
|
|
4688
|
-
for ( let i = 0; i < numberOfTriangles; i ++ ) {
|
|
4689
|
-
|
|
4690
|
-
if ( i % 2 === 0 ) {
|
|
4691
|
-
|
|
4692
|
-
newIndices.push( index.getX( i ) );
|
|
4693
|
-
newIndices.push( index.getX( i + 1 ) );
|
|
4694
|
-
newIndices.push( index.getX( i + 2 ) );
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
} else {
|
|
4698
|
-
|
|
4699
|
-
newIndices.push( index.getX( i + 2 ) );
|
|
4700
|
-
newIndices.push( index.getX( i + 1 ) );
|
|
4701
|
-
newIndices.push( index.getX( i ) );
|
|
4702
|
-
|
|
4703
|
-
}
|
|
4704
|
-
|
|
4705
|
-
}
|
|
4706
|
-
|
|
4707
|
-
}
|
|
4708
|
-
|
|
4709
|
-
if ( ( newIndices.length / 3 ) !== numberOfTriangles ) {
|
|
4710
|
-
|
|
4711
|
-
console.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Unable to generate correct amount of triangles.' );
|
|
4712
|
-
|
|
4713
|
-
}
|
|
4714
|
-
|
|
4715
|
-
// build final geometry
|
|
4716
|
-
|
|
4717
|
-
const newGeometry = geometry.clone();
|
|
4718
|
-
newGeometry.setIndex( newIndices );
|
|
4719
|
-
|
|
4720
|
-
return newGeometry;
|
|
4721
|
-
|
|
4722
|
-
}
|
|
4723
|
-
|
|
4724
4311
|
export { GLTFLoader };
|
|
@@ -1225,6 +1225,112 @@ function mergeGroups( geometry ) {
|
|
|
1225
1225
|
|
|
1226
1226
|
}
|
|
1227
1227
|
|
|
1228
|
+
|
|
1229
|
+
// Creates a new, non-indexed geometry with smooth normals everywhere except faces that meet at
|
|
1230
|
+
// an angle greater than the crease angle.
|
|
1231
|
+
function toCreasedNormals( geometry, creaseAngle = Math.PI / 3 /* 60 degrees */ ) {
|
|
1232
|
+
|
|
1233
|
+
const creaseDot = Math.cos( creaseAngle );
|
|
1234
|
+
const hashMultiplier = ( 1 + 1e-10 ) * 1e2;
|
|
1235
|
+
|
|
1236
|
+
// reusable vertors
|
|
1237
|
+
const verts = [ new Vector3(), new Vector3(), new Vector3() ];
|
|
1238
|
+
const tempVec1 = new Vector3();
|
|
1239
|
+
const tempVec2 = new Vector3();
|
|
1240
|
+
const tempNorm = new Vector3();
|
|
1241
|
+
const tempNorm2 = new Vector3();
|
|
1242
|
+
|
|
1243
|
+
// hashes a vector
|
|
1244
|
+
function hashVertex( v ) {
|
|
1245
|
+
|
|
1246
|
+
const x = ~ ~ ( v.x * hashMultiplier );
|
|
1247
|
+
const y = ~ ~ ( v.y * hashMultiplier );
|
|
1248
|
+
const z = ~ ~ ( v.z * hashMultiplier );
|
|
1249
|
+
return `${x},${y},${z}`;
|
|
1250
|
+
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
const resultGeometry = geometry.toNonIndexed();
|
|
1254
|
+
const posAttr = resultGeometry.attributes.position;
|
|
1255
|
+
const vertexMap = {};
|
|
1256
|
+
|
|
1257
|
+
// find all the normals shared by commonly located vertices
|
|
1258
|
+
for ( let i = 0, l = posAttr.count / 3; i < l; i ++ ) {
|
|
1259
|
+
|
|
1260
|
+
const i3 = 3 * i;
|
|
1261
|
+
const a = verts[ 0 ].fromBufferAttribute( posAttr, i3 + 0 );
|
|
1262
|
+
const b = verts[ 1 ].fromBufferAttribute( posAttr, i3 + 1 );
|
|
1263
|
+
const c = verts[ 2 ].fromBufferAttribute( posAttr, i3 + 2 );
|
|
1264
|
+
|
|
1265
|
+
tempVec1.subVectors( c, b );
|
|
1266
|
+
tempVec2.subVectors( a, b );
|
|
1267
|
+
|
|
1268
|
+
// add the normal to the map for all vertices
|
|
1269
|
+
const normal = new Vector3().crossVectors( tempVec1, tempVec2 ).normalize();
|
|
1270
|
+
for ( let n = 0; n < 3; n ++ ) {
|
|
1271
|
+
|
|
1272
|
+
const vert = verts[ n ];
|
|
1273
|
+
const hash = hashVertex( vert );
|
|
1274
|
+
if ( ! ( hash in vertexMap ) ) {
|
|
1275
|
+
|
|
1276
|
+
vertexMap[ hash ] = [];
|
|
1277
|
+
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
vertexMap[ hash ].push( normal );
|
|
1281
|
+
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
// average normals from all vertices that share a common location if they are within the
|
|
1287
|
+
// provided crease threshold
|
|
1288
|
+
const normalArray = new Float32Array( posAttr.count * 3 );
|
|
1289
|
+
const normAttr = new BufferAttribute( normalArray, 3, false );
|
|
1290
|
+
for ( let i = 0, l = posAttr.count / 3; i < l; i ++ ) {
|
|
1291
|
+
|
|
1292
|
+
// get the face normal for this vertex
|
|
1293
|
+
const i3 = 3 * i;
|
|
1294
|
+
const a = verts[ 0 ].fromBufferAttribute( posAttr, i3 + 0 );
|
|
1295
|
+
const b = verts[ 1 ].fromBufferAttribute( posAttr, i3 + 1 );
|
|
1296
|
+
const c = verts[ 2 ].fromBufferAttribute( posAttr, i3 + 2 );
|
|
1297
|
+
|
|
1298
|
+
tempVec1.subVectors( c, b );
|
|
1299
|
+
tempVec2.subVectors( a, b );
|
|
1300
|
+
|
|
1301
|
+
tempNorm.crossVectors( tempVec1, tempVec2 ).normalize();
|
|
1302
|
+
|
|
1303
|
+
// average all normals that meet the threshold and set the normal value
|
|
1304
|
+
for ( let n = 0; n < 3; n ++ ) {
|
|
1305
|
+
|
|
1306
|
+
const vert = verts[ n ];
|
|
1307
|
+
const hash = hashVertex( vert );
|
|
1308
|
+
const otherNormals = vertexMap[ hash ];
|
|
1309
|
+
tempNorm2.set( 0, 0, 0 );
|
|
1310
|
+
|
|
1311
|
+
for ( let k = 0, lk = otherNormals.length; k < lk; k ++ ) {
|
|
1312
|
+
|
|
1313
|
+
const otherNorm = otherNormals[ k ];
|
|
1314
|
+
if ( tempNorm.dot( otherNorm ) > creaseDot ) {
|
|
1315
|
+
|
|
1316
|
+
tempNorm2.add( otherNorm );
|
|
1317
|
+
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
tempNorm2.normalize();
|
|
1323
|
+
normAttr.setXYZ( i3 + n, tempNorm2.x, tempNorm2.y, tempNorm2.z );
|
|
1324
|
+
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
resultGeometry.setAttribute( 'normal', normAttr );
|
|
1330
|
+
return resultGeometry;
|
|
1331
|
+
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1228
1334
|
export {
|
|
1229
1335
|
computeTangents,
|
|
1230
1336
|
computeMikkTSpaceTangents,
|
|
@@ -1235,5 +1341,6 @@ export {
|
|
|
1235
1341
|
mergeVertices,
|
|
1236
1342
|
toTrianglesDrawMode,
|
|
1237
1343
|
computeMorphedAttributes,
|
|
1238
|
-
mergeGroups
|
|
1344
|
+
mergeGroups,
|
|
1345
|
+
toCreasedNormals
|
|
1239
1346
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@damienmortini/three",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.182",
|
|
4
4
|
"description": "Three.js helpers",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"install": "npm run copyexamples",
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
"bugs": "https://github.com/damienmortini/lib/issues",
|
|
29
29
|
"homepage": "https://github.com/damienmortini/lib/tree/main/packages/three",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@damienmortini/core": "^0.2.
|
|
31
|
+
"@damienmortini/core": "^0.2.143",
|
|
32
32
|
"fs-extra": "^11.1.0",
|
|
33
33
|
"three": "0.149.0"
|
|
34
34
|
},
|
|
35
|
-
"gitHead": "
|
|
35
|
+
"gitHead": "9c39ac87a4d53c7be6b0c9cf128b892e4fd3abc3"
|
|
36
36
|
}
|