super-three 0.158.0 → 0.160.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/three.cjs +1719 -379
- package/build/three.js +1719 -379
- package/build/three.min.js +1 -1
- package/build/three.module.js +1718 -380
- package/build/three.module.min.js +1 -1
- package/examples/jsm/Addons.js +2 -1
- package/examples/jsm/controls/OrbitControls.js +50 -40
- package/examples/jsm/csm/CSMShader.js +52 -47
- package/examples/jsm/exporters/GLTFExporter.js +79 -1
- package/examples/jsm/exporters/USDZExporter.js +27 -19
- package/examples/jsm/helpers/TextureHelper.js +237 -0
- package/examples/jsm/interactive/HTMLMesh.js +9 -2
- package/examples/jsm/lines/LineMaterial.js +16 -33
- package/examples/jsm/loaders/ColladaLoader.js +0 -6
- package/examples/jsm/loaders/DRACOLoader.js +4 -3
- package/examples/jsm/loaders/FBXLoader.js +294 -124
- package/examples/jsm/loaders/GLTFLoader.js +71 -3
- package/examples/jsm/loaders/MaterialXLoader.js +73 -54
- package/examples/jsm/loaders/NRRDLoader.js +0 -13
- package/examples/jsm/loaders/SVGLoader.js +4 -4
- package/examples/jsm/loaders/USDZLoader.js +3 -17
- package/examples/jsm/math/Octree.js +15 -4
- package/examples/jsm/misc/Timer.js +119 -0
- package/examples/jsm/misc/TubePainter.js +3 -6
- package/examples/jsm/modifiers/CurveModifier.js +20 -2
- package/examples/jsm/nodes/Nodes.js +11 -7
- package/examples/jsm/nodes/accessors/CameraNode.js +18 -2
- package/examples/jsm/nodes/accessors/CubeTextureNode.js +5 -73
- package/examples/jsm/nodes/accessors/MaterialReferenceNode.js +11 -2
- package/examples/jsm/nodes/accessors/ModelNode.js +1 -1
- package/examples/jsm/nodes/accessors/ModelViewProjectionNode.js +12 -3
- package/examples/jsm/nodes/accessors/MorphNode.js +191 -16
- package/examples/jsm/nodes/accessors/ReferenceNode.js +25 -1
- package/examples/jsm/nodes/accessors/TextureNode.js +122 -36
- package/examples/jsm/nodes/code/CodeNode.js +3 -3
- package/examples/jsm/nodes/core/AttributeNode.js +7 -1
- package/examples/jsm/nodes/core/CacheNode.js +4 -1
- package/examples/jsm/nodes/core/ConstNode.js +1 -1
- package/examples/jsm/nodes/core/Node.js +6 -3
- package/examples/jsm/nodes/core/NodeBuilder.js +84 -27
- package/examples/jsm/nodes/core/NodeFrame.js +10 -8
- package/examples/jsm/nodes/core/NodeUniform.js +12 -0
- package/examples/jsm/nodes/core/NodeUtils.js +3 -7
- package/examples/jsm/nodes/core/OutputStructNode.js +3 -3
- package/examples/jsm/nodes/core/PropertyNode.js +17 -2
- package/examples/jsm/nodes/core/StructTypeNode.js +4 -4
- package/examples/jsm/nodes/core/UniformGroup.js +13 -0
- package/examples/jsm/nodes/core/UniformGroupNode.js +36 -0
- package/examples/jsm/nodes/core/UniformNode.js +17 -0
- package/examples/jsm/nodes/core/VarNode.js +2 -0
- package/examples/jsm/nodes/core/VaryingNode.js +1 -7
- package/examples/jsm/nodes/display/BumpMapNode.js +1 -1
- package/examples/jsm/nodes/display/ColorAdjustmentNode.js +6 -10
- package/examples/jsm/nodes/display/GaussianBlurNode.js +170 -0
- package/examples/jsm/nodes/display/PassNode.js +182 -0
- package/examples/jsm/nodes/display/ViewportDepthNode.js +31 -3
- package/examples/jsm/nodes/display/ViewportDepthTextureNode.js +2 -2
- package/examples/jsm/nodes/display/ViewportNode.js +5 -8
- package/examples/jsm/nodes/functions/PhysicalLightingModel.js +1 -1
- package/examples/jsm/nodes/lighting/AnalyticLightNode.js +52 -17
- package/examples/jsm/nodes/lighting/EnvironmentNode.js +8 -12
- package/examples/jsm/nodes/lighting/LightsNode.js +34 -32
- package/examples/jsm/nodes/materials/InstancedPointsNodeMaterial.js +1 -1
- package/examples/jsm/nodes/materials/Line2NodeMaterial.js +12 -12
- package/examples/jsm/nodes/materials/MeshBasicNodeMaterial.js +1 -0
- package/examples/jsm/nodes/materials/MeshNormalNodeMaterial.js +1 -1
- package/examples/jsm/nodes/materials/NodeMaterial.js +66 -41
- package/examples/jsm/nodes/materials/PointsNodeMaterial.js +0 -10
- package/examples/jsm/nodes/materials/SpriteNodeMaterial.js +0 -7
- package/examples/jsm/nodes/materialx/MaterialXNodes.js +10 -10
- package/examples/jsm/nodes/materialx/lib/mx_hsv.js +128 -54
- package/examples/jsm/nodes/materialx/lib/mx_noise.js +1430 -618
- package/examples/jsm/nodes/materialx/lib/mx_transform_color.js +24 -14
- package/examples/jsm/nodes/math/MathNode.js +2 -0
- package/examples/jsm/nodes/math/OperatorNode.js +19 -6
- package/examples/jsm/nodes/shadernode/ShaderNode.js +32 -3
- package/examples/jsm/nodes/utils/FunctionOverloadingNode.js +95 -0
- package/examples/jsm/nodes/utils/RemapNode.js +2 -2
- package/examples/jsm/nodes/utils/SplitNode.js +8 -2
- package/examples/jsm/nodes/utils/TriplanarTexturesNode.js +3 -3
- package/examples/jsm/objects/QuadMesh.js +60 -0
- package/examples/jsm/postprocessing/GTAOPass.js +572 -0
- package/examples/jsm/postprocessing/OutputPass.js +2 -0
- package/examples/jsm/renderers/common/Animation.js +10 -21
- package/examples/jsm/renderers/common/Backend.js +19 -3
- package/examples/jsm/renderers/common/Background.js +20 -22
- package/examples/jsm/renderers/common/Bindings.js +30 -21
- package/examples/jsm/renderers/common/ChainMap.js +3 -3
- package/examples/jsm/renderers/common/Color4.js +37 -0
- package/examples/jsm/renderers/common/Geometries.js +4 -4
- package/examples/jsm/renderers/common/Info.js +12 -2
- package/examples/jsm/renderers/common/Pipelines.js +3 -51
- package/examples/jsm/renderers/common/PostProcessing.js +25 -0
- package/examples/jsm/renderers/common/RenderContext.js +1 -1
- package/examples/jsm/renderers/common/RenderContexts.js +1 -1
- package/examples/jsm/renderers/common/RenderObject.js +13 -1
- package/examples/jsm/renderers/common/RenderObjects.js +4 -2
- package/examples/jsm/renderers/common/Renderer.js +137 -37
- package/examples/jsm/renderers/common/StorageTexture.js +1 -0
- package/examples/jsm/renderers/common/Textures.js +4 -1
- package/examples/jsm/renderers/common/nodes/NodeBuilderState.js +10 -2
- package/examples/jsm/renderers/common/nodes/NodeUniformsGroup.js +44 -0
- package/examples/jsm/renderers/common/nodes/Nodes.js +74 -7
- package/examples/jsm/renderers/webgl/WebGLBackend.js +91 -33
- package/examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js +100 -31
- package/examples/jsm/renderers/webgl/utils/WebGLAttributeUtils.js +57 -5
- package/examples/jsm/renderers/webgl/utils/WebGLCapabilities.js +36 -0
- package/examples/jsm/renderers/webgl/utils/WebGLExtensions.js +11 -1
- package/examples/jsm/renderers/webgl/utils/WebGLTextureUtils.js +71 -2
- package/examples/jsm/renderers/webgl/utils/WebGLUtils.js +42 -0
- package/examples/jsm/renderers/webgl-legacy/nodes/SlotNode.js +1 -1
- package/examples/jsm/renderers/webgl-legacy/nodes/WebGLNodeBuilder.js +33 -3
- package/examples/jsm/renderers/webgl-legacy/nodes/WebGLNodes.js +4 -14
- package/examples/jsm/renderers/webgpu/WebGPUBackend.js +186 -137
- package/examples/jsm/renderers/webgpu/WebGPURenderer.js +1 -1
- package/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js +209 -90
- package/examples/jsm/renderers/webgpu/utils/WebGPUAttributeUtils.js +15 -10
- package/examples/jsm/renderers/webgpu/utils/WebGPUBindingUtils.js +11 -3
- package/examples/jsm/renderers/webgpu/utils/WebGPUPipelineUtils.js +2 -3
- package/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js +88 -6
- package/examples/jsm/shaders/FXAAShader.js +133 -133
- package/examples/jsm/shaders/GTAOShader.js +424 -0
- package/examples/jsm/shaders/OutputShader.js +4 -0
- package/examples/jsm/shaders/PoissonDenoiseShader.js +226 -0
- package/examples/jsm/shaders/SAOShader.js +2 -3
- package/examples/jsm/shaders/SSAOShader.js +2 -3
- package/examples/jsm/transpiler/AST.js +40 -1
- package/examples/jsm/transpiler/GLSLDecoder.js +50 -8
- package/examples/jsm/transpiler/ShaderToyDecoder.js +4 -4
- package/examples/jsm/transpiler/TSLEncoder.js +124 -20
- package/examples/jsm/utils/SortUtils.js +158 -0
- package/examples/jsm/utils/TextureUtils.js +33 -21
- package/examples/jsm/webxr/ARButton.js +14 -0
- package/examples/jsm/webxr/VRButton.js +23 -8
- package/examples/jsm/webxr/XRButton.js +25 -11
- package/package.json +5 -6
- package/src/Three.js +1 -0
- package/src/constants.js +2 -1
- package/src/core/BufferAttribute.js +21 -2
- package/src/core/InterleavedBuffer.js +21 -1
- package/src/core/Object3D.js +60 -12
- package/src/core/UniformsGroup.js +7 -1
- package/src/extras/curves/LineCurve3.js +4 -0
- package/src/loaders/AudioLoader.js +1 -1
- package/src/loaders/BufferGeometryLoader.js +0 -7
- package/src/loaders/ImageBitmapLoader.js +25 -1
- package/src/loaders/ObjectLoader.js +49 -0
- package/src/materials/ShaderMaterial.js +2 -1
- package/src/math/ColorManagement.js +0 -16
- package/src/math/Quaternion.js +5 -4
- package/src/math/Sphere.js +2 -0
- package/src/math/Triangle.js +17 -5
- package/src/objects/BatchedMesh.js +1020 -0
- package/src/objects/Skeleton.js +1 -3
- package/src/renderers/WebGL3DRenderTarget.js +2 -2
- package/src/renderers/WebGLArrayRenderTarget.js +2 -2
- package/src/renderers/WebGLRenderer.js +23 -18
- package/src/renderers/shaders/ShaderChunk/batching_pars_vertex.glsl.js +19 -0
- package/src/renderers/shaders/ShaderChunk/batching_vertex.glsl.js +5 -0
- package/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js +0 -5
- package/src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl.js +31 -4
- package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +9 -4
- package/src/renderers/shaders/ShaderChunk/project_vertex.glsl.js +6 -0
- package/src/renderers/shaders/ShaderChunk/skinning_pars_vertex.glsl.js +9 -17
- package/src/renderers/shaders/ShaderChunk/tonemapping_pars_fragment.glsl.js +84 -0
- package/src/renderers/shaders/ShaderChunk/worldpos_vertex.glsl.js +6 -0
- package/src/renderers/shaders/ShaderChunk.js +4 -0
- package/src/renderers/shaders/ShaderLib/depth.glsl.js +2 -0
- package/src/renderers/shaders/ShaderLib/distanceRGBA.glsl.js +2 -0
- package/src/renderers/shaders/ShaderLib/meshbasic.glsl.js +2 -0
- package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +2 -0
- package/src/renderers/shaders/ShaderLib/meshmatcap.glsl.js +3 -0
- package/src/renderers/shaders/ShaderLib/meshnormal.glsl.js +2 -0
- package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +2 -0
- package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +2 -0
- package/src/renderers/shaders/ShaderLib/meshtoon.glsl.js +2 -0
- package/src/renderers/shaders/ShaderLib/shadow.glsl.js +3 -0
- package/src/renderers/webgl/WebGLAttributes.js +39 -5
- package/src/renderers/webgl/WebGLBufferRenderer.js +31 -0
- package/src/renderers/webgl/WebGLCubeMaps.js +1 -1
- package/src/renderers/webgl/WebGLExtensions.js +1 -0
- package/src/renderers/webgl/WebGLIndexedBufferRenderer.js +31 -0
- package/src/renderers/webgl/WebGLLights.js +11 -2
- package/src/renderers/webgl/WebGLProgram.js +20 -1
- package/src/renderers/webgl/WebGLPrograms.js +5 -0
- package/src/renderers/webgl/WebGLShadowMap.js +35 -0
- package/src/renderers/webgl/WebGLTextures.js +7 -11
- package/src/renderers/webgl/WebGLUniforms.js +11 -1
- package/src/renderers/webgl/WebGLUniformsGroups.js +72 -93
- package/src/renderers/webxr/WebXRManager.js +16 -0
- package/examples/jsm/objects/BatchedMesh.js +0 -586
|
@@ -36,10 +36,12 @@ import {
|
|
|
36
36
|
Texture,
|
|
37
37
|
TextureLoader,
|
|
38
38
|
Uint16BufferAttribute,
|
|
39
|
+
Vector2,
|
|
39
40
|
Vector3,
|
|
40
41
|
Vector4,
|
|
41
42
|
VectorKeyframeTrack,
|
|
42
|
-
SRGBColorSpace
|
|
43
|
+
SRGBColorSpace,
|
|
44
|
+
ShapeUtils
|
|
43
45
|
} from 'three';
|
|
44
46
|
import * as fflate from '../libs/fflate.module.js';
|
|
45
47
|
import { NURBSCurve } from '../curves/NURBSCurve.js';
|
|
@@ -443,6 +445,22 @@ class FBXTreeParser {
|
|
|
443
445
|
|
|
444
446
|
}
|
|
445
447
|
|
|
448
|
+
} else if ( extension === 'dds' ) {
|
|
449
|
+
|
|
450
|
+
const loader = this.manager.getHandler( '.dds' );
|
|
451
|
+
|
|
452
|
+
if ( loader === null ) {
|
|
453
|
+
|
|
454
|
+
console.warn( 'FBXLoader: DDS loader not found, creating placeholder texture for', textureNode.RelativeFilename );
|
|
455
|
+
texture = new Texture();
|
|
456
|
+
|
|
457
|
+
} else {
|
|
458
|
+
|
|
459
|
+
loader.setPath( this.textureLoader.path );
|
|
460
|
+
texture = loader.load( fileName );
|
|
461
|
+
|
|
462
|
+
}
|
|
463
|
+
|
|
446
464
|
} else if ( extension === 'psd' ) {
|
|
447
465
|
|
|
448
466
|
console.warn( 'FBXLoader: PSD textures are not supported, creating placeholder texture for', textureNode.RelativeFilename );
|
|
@@ -883,7 +901,7 @@ class FBXTreeParser {
|
|
|
883
901
|
|
|
884
902
|
this.bindSkeleton( deformers.skeletons, geometryMap, modelMap );
|
|
885
903
|
|
|
886
|
-
this.
|
|
904
|
+
this.addGlobalSceneSettings();
|
|
887
905
|
|
|
888
906
|
sceneGraph.traverse( function ( node ) {
|
|
889
907
|
|
|
@@ -1466,20 +1484,31 @@ class FBXTreeParser {
|
|
|
1466
1484
|
|
|
1467
1485
|
}
|
|
1468
1486
|
|
|
1469
|
-
|
|
1470
|
-
|
|
1487
|
+
addGlobalSceneSettings() {
|
|
1488
|
+
|
|
1489
|
+
if ( 'GlobalSettings' in fbxTree ) {
|
|
1471
1490
|
|
|
1472
|
-
|
|
1491
|
+
if ( 'AmbientColor' in fbxTree.GlobalSettings ) {
|
|
1473
1492
|
|
|
1474
|
-
|
|
1475
|
-
const r = ambientColor[ 0 ];
|
|
1476
|
-
const g = ambientColor[ 1 ];
|
|
1477
|
-
const b = ambientColor[ 2 ];
|
|
1493
|
+
// Parse ambient color - if it's not set to black (default), create an ambient light
|
|
1478
1494
|
|
|
1479
|
-
|
|
1495
|
+
const ambientColor = fbxTree.GlobalSettings.AmbientColor.value;
|
|
1496
|
+
const r = ambientColor[ 0 ];
|
|
1497
|
+
const g = ambientColor[ 1 ];
|
|
1498
|
+
const b = ambientColor[ 2 ];
|
|
1480
1499
|
|
|
1481
|
-
|
|
1482
|
-
|
|
1500
|
+
if ( r !== 0 || g !== 0 || b !== 0 ) {
|
|
1501
|
+
|
|
1502
|
+
const color = new Color( r, g, b ).convertSRGBToLinear();
|
|
1503
|
+
sceneGraph.add( new AmbientLight( color, 1 ) );
|
|
1504
|
+
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
if ( 'UnitScaleFactor' in fbxTree.GlobalSettings ) {
|
|
1510
|
+
|
|
1511
|
+
sceneGraph.userData.unitScaleFactor = fbxTree.GlobalSettings.UnitScaleFactor.value;
|
|
1483
1512
|
|
|
1484
1513
|
}
|
|
1485
1514
|
|
|
@@ -1944,8 +1973,6 @@ class GeometryParser {
|
|
|
1944
1973
|
|
|
1945
1974
|
if ( endOfFace ) {
|
|
1946
1975
|
|
|
1947
|
-
if ( faceLength > 4 ) console.warn( 'THREE.FBXLoader: Polygons with more than four sides are not supported. Make sure to triangulate the geometry during export.' );
|
|
1948
|
-
|
|
1949
1976
|
scope.genFace( buffers, geoInfo, facePositionIndexes, materialIndex, faceNormals, faceColors, faceUVs, faceWeights, faceWeightIndices, faceLength );
|
|
1950
1977
|
|
|
1951
1978
|
polygonIndex ++;
|
|
@@ -1967,70 +1994,153 @@ class GeometryParser {
|
|
|
1967
1994
|
|
|
1968
1995
|
}
|
|
1969
1996
|
|
|
1997
|
+
// See https://www.khronos.org/opengl/wiki/Calculating_a_Surface_Normal
|
|
1998
|
+
getNormalNewell( vertices ) {
|
|
1999
|
+
|
|
2000
|
+
const normal = new Vector3( 0.0, 0.0, 0.0 );
|
|
2001
|
+
|
|
2002
|
+
for ( let i = 0; i < vertices.length; i ++ ) {
|
|
2003
|
+
|
|
2004
|
+
const current = vertices[ i ];
|
|
2005
|
+
const next = vertices[ ( i + 1 ) % vertices.length ];
|
|
2006
|
+
|
|
2007
|
+
normal.x += ( current.y - next.y ) * ( current.z + next.z );
|
|
2008
|
+
normal.y += ( current.z - next.z ) * ( current.x + next.x );
|
|
2009
|
+
normal.z += ( current.x - next.x ) * ( current.y + next.y );
|
|
2010
|
+
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
normal.normalize();
|
|
2014
|
+
|
|
2015
|
+
return normal;
|
|
2016
|
+
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
getNormalTangentAndBitangent( vertices ) {
|
|
2020
|
+
|
|
2021
|
+
const normalVector = this.getNormalNewell( vertices );
|
|
2022
|
+
// Avoid up being equal or almost equal to normalVector
|
|
2023
|
+
const up = Math.abs( normalVector.z ) > 0.5 ? new Vector3( 0.0, 1.0, 0.0 ) : new Vector3( 0.0, 0.0, 1.0 );
|
|
2024
|
+
const tangent = up.cross( normalVector ).normalize();
|
|
2025
|
+
const bitangent = normalVector.clone().cross( tangent ).normalize();
|
|
2026
|
+
|
|
2027
|
+
return {
|
|
2028
|
+
normal: normalVector,
|
|
2029
|
+
tangent: tangent,
|
|
2030
|
+
bitangent: bitangent
|
|
2031
|
+
};
|
|
2032
|
+
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2035
|
+
flattenVertex( vertex, normalTangent, normalBitangent ) {
|
|
2036
|
+
|
|
2037
|
+
return new Vector2(
|
|
2038
|
+
vertex.dot( normalTangent ),
|
|
2039
|
+
vertex.dot( normalBitangent )
|
|
2040
|
+
);
|
|
2041
|
+
|
|
2042
|
+
}
|
|
2043
|
+
|
|
1970
2044
|
// Generate data for a single face in a geometry. If the face is a quad then split it into 2 tris
|
|
1971
2045
|
genFace( buffers, geoInfo, facePositionIndexes, materialIndex, faceNormals, faceColors, faceUVs, faceWeights, faceWeightIndices, faceLength ) {
|
|
1972
2046
|
|
|
1973
|
-
|
|
2047
|
+
let triangles;
|
|
2048
|
+
|
|
2049
|
+
if ( faceLength > 3 ) {
|
|
2050
|
+
|
|
2051
|
+
// Triangulate n-gon using earcut
|
|
1974
2052
|
|
|
1975
|
-
|
|
1976
|
-
buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ 1 ] ] );
|
|
1977
|
-
buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ 2 ] ] );
|
|
2053
|
+
const vertices = [];
|
|
1978
2054
|
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
2055
|
+
for ( let i = 0; i < facePositionIndexes.length; i += 3 ) {
|
|
2056
|
+
|
|
2057
|
+
vertices.push( new Vector3(
|
|
2058
|
+
geoInfo.vertexPositions[ facePositionIndexes[ i ] ],
|
|
2059
|
+
geoInfo.vertexPositions[ facePositionIndexes[ i + 1 ] ],
|
|
2060
|
+
geoInfo.vertexPositions[ facePositionIndexes[ i + 2 ] ]
|
|
2061
|
+
) );
|
|
2062
|
+
|
|
2063
|
+
}
|
|
1982
2064
|
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
2065
|
+
const { tangent, bitangent } = this.getNormalTangentAndBitangent( vertices );
|
|
2066
|
+
const triangulationInput = [];
|
|
2067
|
+
|
|
2068
|
+
for ( const vertex of vertices ) {
|
|
2069
|
+
|
|
2070
|
+
triangulationInput.push( this.flattenVertex( vertex, tangent, bitangent ) );
|
|
2071
|
+
|
|
2072
|
+
}
|
|
2073
|
+
|
|
2074
|
+
triangles = ShapeUtils.triangulateShape( triangulationInput, [] );
|
|
2075
|
+
|
|
2076
|
+
} else {
|
|
2077
|
+
|
|
2078
|
+
// Regular triangle, skip earcut triangulation step
|
|
2079
|
+
triangles = [[ 0, 1, 2 ]];
|
|
2080
|
+
|
|
2081
|
+
}
|
|
2082
|
+
|
|
2083
|
+
for ( const [ i0, i1, i2 ] of triangles ) {
|
|
2084
|
+
|
|
2085
|
+
buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i0 * 3 ] ] );
|
|
2086
|
+
buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i0 * 3 + 1 ] ] );
|
|
2087
|
+
buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i0 * 3 + 2 ] ] );
|
|
2088
|
+
|
|
2089
|
+
buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i1 * 3 ] ] );
|
|
2090
|
+
buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i1 * 3 + 1 ] ] );
|
|
2091
|
+
buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i1 * 3 + 2 ] ] );
|
|
2092
|
+
|
|
2093
|
+
buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i2 * 3 ] ] );
|
|
2094
|
+
buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i2 * 3 + 1 ] ] );
|
|
2095
|
+
buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i2 * 3 + 2 ] ] );
|
|
1986
2096
|
|
|
1987
2097
|
if ( geoInfo.skeleton ) {
|
|
1988
2098
|
|
|
1989
|
-
buffers.vertexWeights.push( faceWeights[
|
|
1990
|
-
buffers.vertexWeights.push( faceWeights[ 1 ] );
|
|
1991
|
-
buffers.vertexWeights.push( faceWeights[ 2 ] );
|
|
1992
|
-
buffers.vertexWeights.push( faceWeights[ 3 ] );
|
|
2099
|
+
buffers.vertexWeights.push( faceWeights[ i0 * 4 ] );
|
|
2100
|
+
buffers.vertexWeights.push( faceWeights[ i0 * 4 + 1 ] );
|
|
2101
|
+
buffers.vertexWeights.push( faceWeights[ i0 * 4 + 2 ] );
|
|
2102
|
+
buffers.vertexWeights.push( faceWeights[ i0 * 4 + 3 ] );
|
|
1993
2103
|
|
|
1994
|
-
buffers.vertexWeights.push( faceWeights[
|
|
1995
|
-
buffers.vertexWeights.push( faceWeights[
|
|
1996
|
-
buffers.vertexWeights.push( faceWeights[
|
|
1997
|
-
buffers.vertexWeights.push( faceWeights[
|
|
2104
|
+
buffers.vertexWeights.push( faceWeights[ i1 * 4 ] );
|
|
2105
|
+
buffers.vertexWeights.push( faceWeights[ i1 * 4 + 1 ] );
|
|
2106
|
+
buffers.vertexWeights.push( faceWeights[ i1 * 4 + 2 ] );
|
|
2107
|
+
buffers.vertexWeights.push( faceWeights[ i1 * 4 + 3 ] );
|
|
1998
2108
|
|
|
1999
|
-
buffers.vertexWeights.push( faceWeights[
|
|
2000
|
-
buffers.vertexWeights.push( faceWeights[
|
|
2001
|
-
buffers.vertexWeights.push( faceWeights[
|
|
2002
|
-
buffers.vertexWeights.push( faceWeights[
|
|
2109
|
+
buffers.vertexWeights.push( faceWeights[ i2 * 4 ] );
|
|
2110
|
+
buffers.vertexWeights.push( faceWeights[ i2 * 4 + 1 ] );
|
|
2111
|
+
buffers.vertexWeights.push( faceWeights[ i2 * 4 + 2 ] );
|
|
2112
|
+
buffers.vertexWeights.push( faceWeights[ i2 * 4 + 3 ] );
|
|
2003
2113
|
|
|
2004
|
-
buffers.weightsIndices.push( faceWeightIndices[
|
|
2005
|
-
buffers.weightsIndices.push( faceWeightIndices[ 1 ] );
|
|
2006
|
-
buffers.weightsIndices.push( faceWeightIndices[ 2 ] );
|
|
2007
|
-
buffers.weightsIndices.push( faceWeightIndices[ 3 ] );
|
|
2114
|
+
buffers.weightsIndices.push( faceWeightIndices[ i0 * 4 ] );
|
|
2115
|
+
buffers.weightsIndices.push( faceWeightIndices[ i0 * 4 + 1 ] );
|
|
2116
|
+
buffers.weightsIndices.push( faceWeightIndices[ i0 * 4 + 2 ] );
|
|
2117
|
+
buffers.weightsIndices.push( faceWeightIndices[ i0 * 4 + 3 ] );
|
|
2008
2118
|
|
|
2009
|
-
buffers.weightsIndices.push( faceWeightIndices[
|
|
2010
|
-
buffers.weightsIndices.push( faceWeightIndices[
|
|
2011
|
-
buffers.weightsIndices.push( faceWeightIndices[
|
|
2012
|
-
buffers.weightsIndices.push( faceWeightIndices[
|
|
2119
|
+
buffers.weightsIndices.push( faceWeightIndices[ i1 * 4 ] );
|
|
2120
|
+
buffers.weightsIndices.push( faceWeightIndices[ i1 * 4 + 1 ] );
|
|
2121
|
+
buffers.weightsIndices.push( faceWeightIndices[ i1 * 4 + 2 ] );
|
|
2122
|
+
buffers.weightsIndices.push( faceWeightIndices[ i1 * 4 + 3 ] );
|
|
2013
2123
|
|
|
2014
|
-
buffers.weightsIndices.push( faceWeightIndices[
|
|
2015
|
-
buffers.weightsIndices.push( faceWeightIndices[
|
|
2016
|
-
buffers.weightsIndices.push( faceWeightIndices[
|
|
2017
|
-
buffers.weightsIndices.push( faceWeightIndices[
|
|
2124
|
+
buffers.weightsIndices.push( faceWeightIndices[ i2 * 4 ] );
|
|
2125
|
+
buffers.weightsIndices.push( faceWeightIndices[ i2 * 4 + 1 ] );
|
|
2126
|
+
buffers.weightsIndices.push( faceWeightIndices[ i2 * 4 + 2 ] );
|
|
2127
|
+
buffers.weightsIndices.push( faceWeightIndices[ i2 * 4 + 3 ] );
|
|
2018
2128
|
|
|
2019
2129
|
}
|
|
2020
2130
|
|
|
2021
2131
|
if ( geoInfo.color ) {
|
|
2022
2132
|
|
|
2023
|
-
buffers.colors.push( faceColors[
|
|
2024
|
-
buffers.colors.push( faceColors[ 1 ] );
|
|
2025
|
-
buffers.colors.push( faceColors[ 2 ] );
|
|
2133
|
+
buffers.colors.push( faceColors[ i0 * 3 ] );
|
|
2134
|
+
buffers.colors.push( faceColors[ i0 * 3 + 1 ] );
|
|
2135
|
+
buffers.colors.push( faceColors[ i0 * 3 + 2 ] );
|
|
2026
2136
|
|
|
2027
|
-
buffers.colors.push( faceColors[
|
|
2028
|
-
buffers.colors.push( faceColors[
|
|
2029
|
-
buffers.colors.push( faceColors[
|
|
2137
|
+
buffers.colors.push( faceColors[ i1 * 3 ] );
|
|
2138
|
+
buffers.colors.push( faceColors[ i1 * 3 + 1 ] );
|
|
2139
|
+
buffers.colors.push( faceColors[ i1 * 3 + 2 ] );
|
|
2030
2140
|
|
|
2031
|
-
buffers.colors.push( faceColors[
|
|
2032
|
-
buffers.colors.push( faceColors[
|
|
2033
|
-
buffers.colors.push( faceColors[
|
|
2141
|
+
buffers.colors.push( faceColors[ i2 * 3 ] );
|
|
2142
|
+
buffers.colors.push( faceColors[ i2 * 3 + 1 ] );
|
|
2143
|
+
buffers.colors.push( faceColors[ i2 * 3 + 2 ] );
|
|
2034
2144
|
|
|
2035
2145
|
}
|
|
2036
2146
|
|
|
@@ -2044,17 +2154,17 @@ class GeometryParser {
|
|
|
2044
2154
|
|
|
2045
2155
|
if ( geoInfo.normal ) {
|
|
2046
2156
|
|
|
2047
|
-
buffers.normal.push( faceNormals[
|
|
2048
|
-
buffers.normal.push( faceNormals[ 1 ] );
|
|
2049
|
-
buffers.normal.push( faceNormals[ 2 ] );
|
|
2157
|
+
buffers.normal.push( faceNormals[ i0 * 3 ] );
|
|
2158
|
+
buffers.normal.push( faceNormals[ i0 * 3 + 1 ] );
|
|
2159
|
+
buffers.normal.push( faceNormals[ i0 * 3 + 2 ] );
|
|
2050
2160
|
|
|
2051
|
-
buffers.normal.push( faceNormals[
|
|
2052
|
-
buffers.normal.push( faceNormals[
|
|
2053
|
-
buffers.normal.push( faceNormals[
|
|
2161
|
+
buffers.normal.push( faceNormals[ i1 * 3 ] );
|
|
2162
|
+
buffers.normal.push( faceNormals[ i1 * 3 + 1 ] );
|
|
2163
|
+
buffers.normal.push( faceNormals[ i1 * 3 + 2 ] );
|
|
2054
2164
|
|
|
2055
|
-
buffers.normal.push( faceNormals[
|
|
2056
|
-
buffers.normal.push( faceNormals[
|
|
2057
|
-
buffers.normal.push( faceNormals[
|
|
2165
|
+
buffers.normal.push( faceNormals[ i2 * 3 ] );
|
|
2166
|
+
buffers.normal.push( faceNormals[ i2 * 3 + 1 ] );
|
|
2167
|
+
buffers.normal.push( faceNormals[ i2 * 3 + 2 ] );
|
|
2058
2168
|
|
|
2059
2169
|
}
|
|
2060
2170
|
|
|
@@ -2064,14 +2174,14 @@ class GeometryParser {
|
|
|
2064
2174
|
|
|
2065
2175
|
if ( buffers.uvs[ j ] === undefined ) buffers.uvs[ j ] = [];
|
|
2066
2176
|
|
|
2067
|
-
buffers.uvs[ j ].push( faceUVs[ j ][
|
|
2068
|
-
buffers.uvs[ j ].push( faceUVs[ j ][ 1 ] );
|
|
2177
|
+
buffers.uvs[ j ].push( faceUVs[ j ][ i0 * 2 ] );
|
|
2178
|
+
buffers.uvs[ j ].push( faceUVs[ j ][ i0 * 2 + 1 ] );
|
|
2069
2179
|
|
|
2070
|
-
buffers.uvs[ j ].push( faceUVs[ j ][
|
|
2071
|
-
buffers.uvs[ j ].push( faceUVs[ j ][
|
|
2180
|
+
buffers.uvs[ j ].push( faceUVs[ j ][ i1 * 2 ] );
|
|
2181
|
+
buffers.uvs[ j ].push( faceUVs[ j ][ i1 * 2 + 1 ] );
|
|
2072
2182
|
|
|
2073
|
-
buffers.uvs[ j ].push( faceUVs[ j ][
|
|
2074
|
-
buffers.uvs[ j ].push( faceUVs[ j ][
|
|
2183
|
+
buffers.uvs[ j ].push( faceUVs[ j ][ i2 * 2 ] );
|
|
2184
|
+
buffers.uvs[ j ].push( faceUVs[ j ][ i2 * 2 + 1 ] );
|
|
2075
2185
|
|
|
2076
2186
|
} );
|
|
2077
2187
|
|
|
@@ -2648,13 +2758,11 @@ class AnimationParser {
|
|
|
2648
2758
|
const tracks = [];
|
|
2649
2759
|
|
|
2650
2760
|
let initialPosition = new Vector3();
|
|
2651
|
-
let initialRotation = new Quaternion();
|
|
2652
2761
|
let initialScale = new Vector3();
|
|
2653
2762
|
|
|
2654
|
-
if ( rawTracks.transform ) rawTracks.transform.decompose( initialPosition,
|
|
2763
|
+
if ( rawTracks.transform ) rawTracks.transform.decompose( initialPosition, new Quaternion(), initialScale );
|
|
2655
2764
|
|
|
2656
2765
|
initialPosition = initialPosition.toArray();
|
|
2657
|
-
initialRotation = new Euler().setFromQuaternion( initialRotation, rawTracks.eulerOrder ).toArray();
|
|
2658
2766
|
initialScale = initialScale.toArray();
|
|
2659
2767
|
|
|
2660
2768
|
if ( rawTracks.T !== undefined && Object.keys( rawTracks.T.curves ).length > 0 ) {
|
|
@@ -2666,7 +2774,7 @@ class AnimationParser {
|
|
|
2666
2774
|
|
|
2667
2775
|
if ( rawTracks.R !== undefined && Object.keys( rawTracks.R.curves ).length > 0 ) {
|
|
2668
2776
|
|
|
2669
|
-
const rotationTrack = this.generateRotationTrack( rawTracks.modelName, rawTracks.R.curves,
|
|
2777
|
+
const rotationTrack = this.generateRotationTrack( rawTracks.modelName, rawTracks.R.curves, rawTracks.preRotation, rawTracks.postRotation, rawTracks.eulerOrder );
|
|
2670
2778
|
if ( rotationTrack !== undefined ) tracks.push( rotationTrack );
|
|
2671
2779
|
|
|
2672
2780
|
}
|
|
@@ -2698,32 +2806,20 @@ class AnimationParser {
|
|
|
2698
2806
|
|
|
2699
2807
|
}
|
|
2700
2808
|
|
|
2701
|
-
generateRotationTrack( modelName, curves,
|
|
2702
|
-
|
|
2703
|
-
if ( curves.x !== undefined ) {
|
|
2809
|
+
generateRotationTrack( modelName, curves, preRotation, postRotation, eulerOrder ) {
|
|
2704
2810
|
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
}
|
|
2811
|
+
let times;
|
|
2812
|
+
let values;
|
|
2709
2813
|
|
|
2710
|
-
if ( curves.y !== undefined ) {
|
|
2711
|
-
|
|
2712
|
-
this.interpolateRotations( curves.y );
|
|
2713
|
-
curves.y.values = curves.y.values.map( MathUtils.degToRad );
|
|
2714
|
-
|
|
2715
|
-
}
|
|
2814
|
+
if ( curves.x !== undefined && curves.y !== undefined && curves.z !== undefined ) {
|
|
2716
2815
|
|
|
2717
|
-
|
|
2816
|
+
const result = this.interpolateRotations( curves.x, curves.y, curves.z, eulerOrder );
|
|
2718
2817
|
|
|
2719
|
-
|
|
2720
|
-
|
|
2818
|
+
times = result[ 0 ];
|
|
2819
|
+
values = result[ 1 ];
|
|
2721
2820
|
|
|
2722
2821
|
}
|
|
2723
2822
|
|
|
2724
|
-
const times = this.getTimesForAllAxes( curves );
|
|
2725
|
-
const values = this.getKeyframeTrackValues( times, curves, initialValue );
|
|
2726
|
-
|
|
2727
2823
|
if ( preRotation !== undefined ) {
|
|
2728
2824
|
|
|
2729
2825
|
preRotation = preRotation.map( MathUtils.degToRad );
|
|
@@ -2749,15 +2845,32 @@ class AnimationParser {
|
|
|
2749
2845
|
|
|
2750
2846
|
const quaternionValues = [];
|
|
2751
2847
|
|
|
2848
|
+
if ( ! values || ! times ) return new QuaternionKeyframeTrack( modelName + '.quaternion', [], [] );
|
|
2849
|
+
|
|
2752
2850
|
for ( let i = 0; i < values.length; i += 3 ) {
|
|
2753
2851
|
|
|
2754
2852
|
euler.set( values[ i ], values[ i + 1 ], values[ i + 2 ], eulerOrder );
|
|
2755
|
-
|
|
2756
2853
|
quaternion.setFromEuler( euler );
|
|
2757
2854
|
|
|
2758
2855
|
if ( preRotation !== undefined ) quaternion.premultiply( preRotation );
|
|
2759
2856
|
if ( postRotation !== undefined ) quaternion.multiply( postRotation );
|
|
2760
2857
|
|
|
2858
|
+
// Check unroll
|
|
2859
|
+
if ( i > 2 ) {
|
|
2860
|
+
|
|
2861
|
+
const prevQuat = new Quaternion().fromArray(
|
|
2862
|
+
quaternionValues,
|
|
2863
|
+
( ( i - 3 ) / 3 ) * 4
|
|
2864
|
+
);
|
|
2865
|
+
|
|
2866
|
+
if ( prevQuat.dot( quaternion ) < 0 ) {
|
|
2867
|
+
|
|
2868
|
+
quaternion.set( - quaternion.x, - quaternion.y, - quaternion.z, - quaternion.w );
|
|
2869
|
+
|
|
2870
|
+
}
|
|
2871
|
+
|
|
2872
|
+
}
|
|
2873
|
+
|
|
2761
2874
|
quaternion.toArray( quaternionValues, ( i / 3 ) * 4 );
|
|
2762
2875
|
|
|
2763
2876
|
}
|
|
@@ -2888,47 +3001,110 @@ class AnimationParser {
|
|
|
2888
3001
|
// Rotations are defined as Euler angles which can have values of any size
|
|
2889
3002
|
// These will be converted to quaternions which don't support values greater than
|
|
2890
3003
|
// PI, so we'll interpolate large rotations
|
|
2891
|
-
interpolateRotations(
|
|
3004
|
+
interpolateRotations( curvex, curvey, curvez, eulerOrder ) {
|
|
2892
3005
|
|
|
2893
|
-
|
|
3006
|
+
const times = [];
|
|
3007
|
+
const values = [];
|
|
3008
|
+
|
|
3009
|
+
// Add first frame
|
|
3010
|
+
times.push( curvex.times[ 0 ] );
|
|
3011
|
+
values.push( MathUtils.degToRad( curvex.values[ 0 ] ) );
|
|
3012
|
+
values.push( MathUtils.degToRad( curvey.values[ 0 ] ) );
|
|
3013
|
+
values.push( MathUtils.degToRad( curvez.values[ 0 ] ) );
|
|
3014
|
+
|
|
3015
|
+
for ( let i = 1; i < curvex.values.length; i ++ ) {
|
|
3016
|
+
|
|
3017
|
+
const initialValue = [
|
|
3018
|
+
curvex.values[ i - 1 ],
|
|
3019
|
+
curvey.values[ i - 1 ],
|
|
3020
|
+
curvez.values[ i - 1 ],
|
|
3021
|
+
];
|
|
3022
|
+
|
|
3023
|
+
if ( isNaN( initialValue[ 0 ] ) || isNaN( initialValue[ 1 ] ) || isNaN( initialValue[ 2 ] ) ) {
|
|
3024
|
+
|
|
3025
|
+
continue;
|
|
3026
|
+
|
|
3027
|
+
}
|
|
3028
|
+
|
|
3029
|
+
const initialValueRad = initialValue.map( MathUtils.degToRad );
|
|
3030
|
+
|
|
3031
|
+
const currentValue = [
|
|
3032
|
+
curvex.values[ i ],
|
|
3033
|
+
curvey.values[ i ],
|
|
3034
|
+
curvez.values[ i ],
|
|
3035
|
+
];
|
|
3036
|
+
|
|
3037
|
+
if ( isNaN( currentValue[ 0 ] ) || isNaN( currentValue[ 1 ] ) || isNaN( currentValue[ 2 ] ) ) {
|
|
3038
|
+
|
|
3039
|
+
continue;
|
|
3040
|
+
|
|
3041
|
+
}
|
|
2894
3042
|
|
|
2895
|
-
const
|
|
2896
|
-
const valuesSpan = curve.values[ i ] - initialValue;
|
|
3043
|
+
const currentValueRad = currentValue.map( MathUtils.degToRad );
|
|
2897
3044
|
|
|
2898
|
-
const
|
|
3045
|
+
const valuesSpan = [
|
|
3046
|
+
currentValue[ 0 ] - initialValue[ 0 ],
|
|
3047
|
+
currentValue[ 1 ] - initialValue[ 1 ],
|
|
3048
|
+
currentValue[ 2 ] - initialValue[ 2 ],
|
|
3049
|
+
];
|
|
2899
3050
|
|
|
2900
|
-
|
|
3051
|
+
const absoluteSpan = [
|
|
3052
|
+
Math.abs( valuesSpan[ 0 ] ),
|
|
3053
|
+
Math.abs( valuesSpan[ 1 ] ),
|
|
3054
|
+
Math.abs( valuesSpan[ 2 ] ),
|
|
3055
|
+
];
|
|
2901
3056
|
|
|
2902
|
-
|
|
3057
|
+
if ( absoluteSpan[ 0 ] >= 180 || absoluteSpan[ 1 ] >= 180 || absoluteSpan[ 2 ] >= 180 ) {
|
|
2903
3058
|
|
|
2904
|
-
const
|
|
2905
|
-
let nextValue = initialValue + step;
|
|
3059
|
+
const maxAbsSpan = Math.max( ...absoluteSpan );
|
|
2906
3060
|
|
|
2907
|
-
const
|
|
2908
|
-
const timeSpan = curve.times[ i ] - initialTime;
|
|
2909
|
-
const interval = timeSpan / numSubIntervals;
|
|
2910
|
-
let nextTime = initialTime + interval;
|
|
3061
|
+
const numSubIntervals = maxAbsSpan / 180;
|
|
2911
3062
|
|
|
2912
|
-
const
|
|
2913
|
-
const
|
|
3063
|
+
const E1 = new Euler( ...initialValueRad, eulerOrder );
|
|
3064
|
+
const E2 = new Euler( ...currentValueRad, eulerOrder );
|
|
2914
3065
|
|
|
2915
|
-
|
|
3066
|
+
const Q1 = new Quaternion().setFromEuler( E1 );
|
|
3067
|
+
const Q2 = new Quaternion().setFromEuler( E2 );
|
|
2916
3068
|
|
|
2917
|
-
|
|
2918
|
-
|
|
3069
|
+
// Check unroll
|
|
3070
|
+
if ( Q1.dot( Q2 ) ) {
|
|
2919
3071
|
|
|
2920
|
-
|
|
2921
|
-
nextValue += step;
|
|
3072
|
+
Q2.set( - Q2.x, - Q2.y, - Q2.z, - Q2.w );
|
|
2922
3073
|
|
|
2923
3074
|
}
|
|
2924
3075
|
|
|
2925
|
-
|
|
2926
|
-
|
|
3076
|
+
// Interpolate
|
|
3077
|
+
const initialTime = curvex.times[ i - 1 ];
|
|
3078
|
+
const timeSpan = curvex.times[ i ] - initialTime;
|
|
3079
|
+
|
|
3080
|
+
const Q = new Quaternion();
|
|
3081
|
+
const E = new Euler();
|
|
3082
|
+
for ( let t = 0; t < 1; t += 1 / numSubIntervals ) {
|
|
3083
|
+
|
|
3084
|
+
Q.copy( Q1.clone().slerp( Q2.clone(), t ) );
|
|
3085
|
+
|
|
3086
|
+
times.push( initialTime + t * timeSpan );
|
|
3087
|
+
E.setFromQuaternion( Q, eulerOrder );
|
|
3088
|
+
|
|
3089
|
+
values.push( E.x );
|
|
3090
|
+
values.push( E.y );
|
|
3091
|
+
values.push( E.z );
|
|
3092
|
+
|
|
3093
|
+
}
|
|
3094
|
+
|
|
3095
|
+
} else {
|
|
3096
|
+
|
|
3097
|
+
times.push( curvex.times[ i ] );
|
|
3098
|
+
values.push( MathUtils.degToRad( curvex.values[ i ] ) );
|
|
3099
|
+
values.push( MathUtils.degToRad( curvey.values[ i ] ) );
|
|
3100
|
+
values.push( MathUtils.degToRad( curvez.values[ i ] ) );
|
|
2927
3101
|
|
|
2928
3102
|
}
|
|
2929
3103
|
|
|
2930
3104
|
}
|
|
2931
3105
|
|
|
3106
|
+
return [ times, values ];
|
|
3107
|
+
|
|
2932
3108
|
}
|
|
2933
3109
|
|
|
2934
3110
|
}
|
|
@@ -4134,11 +4310,5 @@ function slice( a, b, from, to ) {
|
|
|
4134
4310
|
|
|
4135
4311
|
}
|
|
4136
4312
|
|
|
4137
|
-
// inject array a2 into array a1 at index
|
|
4138
|
-
function inject( a1, index, a2 ) {
|
|
4139
|
-
|
|
4140
|
-
return a1.slice( 0, index ).concat( a2 ).concat( a1.slice( index ) );
|
|
4141
|
-
|
|
4142
|
-
}
|
|
4143
4313
|
|
|
4144
4314
|
export { FBXLoader };
|