@plastic-software/three 0.183.3 → 0.184.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 +783 -290
- package/build/three.core.js +372 -110
- package/build/three.core.min.js +1 -1
- package/build/three.module.js +436 -184
- package/build/three.module.min.js +1 -1
- package/build/three.tsl.js +7 -1
- package/build/three.tsl.min.js +1 -1
- package/build/three.webgpu.js +2979 -1281
- package/build/three.webgpu.min.js +1 -1
- package/build/three.webgpu.nodes.js +2942 -1281
- package/build/three.webgpu.nodes.min.js +1 -1
- package/examples/jsm/Addons.js +11 -0
- package/examples/jsm/animation/CCDIKSolver.js +5 -1
- package/examples/jsm/controls/ArcballControls.js +4 -1
- package/examples/jsm/controls/DragControls.js +2 -2
- package/examples/jsm/controls/FirstPersonControls.js +58 -54
- package/examples/jsm/controls/FlyControls.js +4 -0
- package/examples/jsm/controls/OrbitControls.js +2 -2
- package/examples/jsm/controls/TrackballControls.js +2 -2
- package/examples/jsm/controls/TransformControls.js +34 -2
- package/examples/jsm/csm/CSMShadowNode.js +6 -2
- package/examples/jsm/exporters/GLTFExporter.js +21 -5
- package/examples/jsm/geometries/TextGeometry.js +18 -0
- package/examples/jsm/helpers/LightProbeGridHelper.js +221 -0
- package/examples/jsm/inspector/Extension.js +13 -0
- package/examples/jsm/inspector/Inspector.js +169 -114
- package/examples/jsm/inspector/RendererInspector.js +2 -2
- package/examples/jsm/inspector/extensions/extensions.json +6 -0
- package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphEditor.js +916 -0
- package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphLoader.js +281 -0
- package/examples/jsm/inspector/tabs/Memory.js +128 -0
- package/examples/jsm/inspector/tabs/Parameters.js +34 -2
- package/examples/jsm/inspector/tabs/Performance.js +2 -2
- package/examples/jsm/inspector/tabs/Settings.js +264 -0
- package/examples/jsm/inspector/tabs/Timeline.js +1611 -0
- package/examples/jsm/inspector/tabs/Viewer.js +105 -3
- package/examples/jsm/inspector/ui/Graph.js +2 -2
- package/examples/jsm/inspector/ui/List.js +1 -1
- package/examples/jsm/inspector/ui/Profiler.js +273 -176
- package/examples/jsm/inspector/ui/Style.js +64 -10
- package/examples/jsm/inspector/ui/Tab.js +39 -7
- package/examples/jsm/inspector/ui/Values.js +39 -2
- package/examples/jsm/inspector/ui/utils.js +13 -0
- package/examples/jsm/interaction/InteractionManager.js +226 -0
- package/examples/jsm/libs/meshopt_decoder.module.js +8 -8
- package/examples/jsm/lighting/DynamicLighting.js +82 -0
- package/examples/jsm/lighting/LightProbeGrid.js +651 -0
- package/examples/jsm/lines/LineMaterial.js +1 -1
- package/examples/jsm/loaders/EXRLoader.js +682 -43
- package/examples/jsm/loaders/FBXLoader.js +233 -33
- package/examples/jsm/loaders/GLTFLoader.js +24 -7
- package/examples/jsm/loaders/HDRLoader.js +1 -1
- package/examples/jsm/loaders/KTX2Loader.js +8 -2
- package/examples/jsm/loaders/LDrawLoader.js +39 -47
- package/examples/jsm/loaders/SVGLoader.js +1 -1
- package/examples/jsm/loaders/VTKLoader.js +5 -1
- package/examples/jsm/loaders/collada/ColladaComposer.js +101 -7
- package/examples/jsm/loaders/collada/ColladaParser.js +19 -4
- package/examples/jsm/loaders/usd/USDAParser.js +6 -0
- package/examples/jsm/loaders/usd/USDCParser.js +26 -0
- package/examples/jsm/loaders/usd/USDComposer.js +656 -103
- package/examples/jsm/misc/GPUComputationRenderer.js +2 -0
- package/examples/jsm/misc/RollerCoaster.js +42 -4
- package/examples/jsm/modifiers/TessellateModifier.js +1 -1
- package/examples/jsm/objects/Reflector.js +73 -25
- package/examples/jsm/objects/Sky.js +14 -2
- package/examples/jsm/objects/SkyMesh.js +23 -6
- package/examples/jsm/renderers/Projector.js +18 -38
- package/examples/jsm/renderers/SVGRenderer.js +6 -25
- package/examples/jsm/transpiler/GLSLDecoder.js +2 -2
- package/examples/jsm/tsl/WebGLNodesHandler.js +605 -0
- package/examples/jsm/tsl/display/AfterImageNode.js +10 -0
- package/examples/jsm/tsl/display/AnamorphicNode.js +11 -0
- package/examples/jsm/tsl/display/BilateralBlurNode.js +10 -0
- package/examples/jsm/tsl/display/ChromaticAberrationNode.js +3 -36
- package/examples/jsm/tsl/display/FSR1Node.js +477 -0
- package/examples/jsm/tsl/display/GTAONode.js +2 -1
- package/examples/jsm/tsl/display/GaussianBlurNode.js +10 -0
- package/examples/jsm/tsl/display/GodraysNode.js +2 -11
- package/examples/jsm/tsl/display/OutlineNode.js +66 -16
- package/examples/jsm/tsl/display/SSGINode.js +0 -4
- package/examples/jsm/tsl/display/SharpenNode.js +283 -0
- package/examples/jsm/tsl/display/TAAUNode.js +835 -0
- package/examples/jsm/tsl/display/TRAANode.js +48 -7
- package/examples/jsm/tsl/lighting/DynamicLightsNode.js +300 -0
- package/examples/jsm/tsl/lighting/data/AmbientLightDataNode.js +61 -0
- package/examples/jsm/tsl/lighting/data/DirectionalLightDataNode.js +111 -0
- package/examples/jsm/tsl/lighting/data/HemisphereLightDataNode.js +99 -0
- package/examples/jsm/tsl/lighting/data/PointLightDataNode.js +134 -0
- package/examples/jsm/tsl/lighting/data/SpotLightDataNode.js +161 -0
- package/examples/jsm/tsl/math/Bayer.js +13 -2
- package/examples/jsm/utils/BufferGeometryUtils.js +2 -3
- package/examples/jsm/utils/ColorUtils.js +76 -0
- package/examples/jsm/utils/SkeletonUtils.js +14 -8
- package/examples/jsm/webxr/XRHandMeshModel.js +36 -10
- package/examples/jsm/webxr/XRHandModelFactory.js +2 -1
- package/package.json +4 -4
- package/src/Three.Core.js +1 -0
- package/src/Three.TSL.js +6 -0
- package/src/Three.WebGPU.Nodes.js +3 -0
- package/src/Three.WebGPU.js +6 -0
- package/src/animation/AnimationAction.js +11 -1
- package/src/audio/AudioContext.js +2 -2
- package/src/constants.js +1 -1
- package/src/core/BufferAttribute.js +13 -1
- package/src/core/Clock.js +1 -1
- package/src/core/Object3D.js +1 -5
- package/src/core/RenderTarget.js +1 -0
- package/src/extras/PMREMGenerator.js +1 -1
- package/src/extras/curves/CatmullRomCurve3.js +3 -2
- package/src/loaders/AudioLoader.js +11 -1
- package/src/loaders/DataTextureLoader.js +6 -4
- package/src/loaders/FileLoader.js +1 -2
- package/src/loaders/ImageBitmapLoader.js +4 -6
- package/src/loaders/MaterialLoader.js +1 -1
- package/src/loaders/ObjectLoader.js +25 -4
- package/src/loaders/nodes/NodeObjectLoader.js +18 -0
- package/src/materials/MeshToonMaterial.js +1 -1
- package/src/materials/nodes/Line2NodeMaterial.js +27 -0
- package/src/materials/nodes/NodeMaterial.js +0 -27
- package/src/materials/nodes/manager/NodeMaterialObserver.js +188 -89
- package/src/math/Line3.js +3 -0
- package/src/math/Matrix2.js +13 -9
- package/src/math/Matrix3.js +13 -9
- package/src/math/Matrix4.js +13 -9
- package/src/math/Plane.js +4 -3
- package/src/math/Triangle.js +1 -1
- package/src/math/Vector2.js +11 -7
- package/src/math/Vector3.js +12 -8
- package/src/math/Vector4.js +13 -9
- package/src/nodes/Nodes.js +0 -1
- package/src/nodes/TSL.js +1 -1
- package/src/nodes/accessors/BufferAttributeNode.js +9 -3
- package/src/nodes/accessors/CubeTextureNode.js +7 -1
- package/src/nodes/accessors/MaterialProperties.js +2 -5
- package/src/nodes/accessors/Object3DNode.js +1 -1
- package/src/nodes/accessors/ReferenceBaseNode.js +2 -2
- package/src/nodes/accessors/ReferenceNode.js +4 -4
- package/src/nodes/accessors/SceneProperties.js +2 -8
- package/src/nodes/accessors/StorageBufferNode.js +10 -4
- package/src/nodes/accessors/StorageTextureNode.js +4 -9
- package/src/nodes/accessors/TextureNode.js +10 -2
- package/src/nodes/accessors/UniformArrayNode.js +2 -2
- package/src/nodes/code/FunctionCallNode.js +1 -1
- package/src/nodes/code/FunctionNode.js +1 -1
- package/src/nodes/core/ArrayNode.js +1 -1
- package/src/nodes/core/AssignNode.js +1 -1
- package/src/nodes/core/AttributeNode.js +1 -1
- package/src/nodes/core/BypassNode.js +1 -1
- package/src/nodes/core/ContextNode.js +1 -1
- package/src/nodes/core/IndexNode.js +2 -1
- package/src/nodes/core/InputNode.js +1 -1
- package/src/nodes/core/InspectorNode.js +1 -1
- package/src/nodes/core/IsolateNode.js +1 -1
- package/src/nodes/core/Node.js +83 -12
- package/src/nodes/core/NodeBuilder.js +117 -16
- package/src/nodes/core/NodeUtils.js +1 -1
- package/src/nodes/core/OutputStructNode.js +1 -1
- package/src/nodes/core/ParameterNode.js +1 -1
- package/src/nodes/core/StackNode.js +1 -1
- package/src/nodes/core/StructNode.js +1 -1
- package/src/nodes/core/StructTypeNode.js +1 -1
- package/src/nodes/core/SubBuildNode.js +1 -1
- package/src/nodes/core/UniformGroupNode.js +36 -6
- package/src/nodes/core/VarNode.js +1 -1
- package/src/nodes/core/VaryingNode.js +1 -1
- package/src/nodes/display/NormalMapNode.js +2 -2
- package/src/nodes/display/PassNode.js +27 -7
- package/src/nodes/display/RenderOutputNode.js +4 -4
- package/src/nodes/display/ScreenNode.js +1 -1
- package/src/nodes/display/ViewportDepthTextureNode.js +11 -15
- package/src/nodes/display/ViewportTextureNode.js +18 -7
- package/src/nodes/functions/BSDF/V_GGX_SmithCorrelated_Anisotropic.js +2 -2
- package/src/nodes/geometry/RangeNode.js +1 -1
- package/src/nodes/gpgpu/AtomicFunctionNode.js +1 -1
- package/src/nodes/gpgpu/BarrierNode.js +9 -0
- package/src/nodes/gpgpu/ComputeBuiltinNode.js +1 -1
- package/src/nodes/gpgpu/ComputeNode.js +69 -44
- package/src/nodes/gpgpu/SubgroupFunctionNode.js +1 -1
- package/src/nodes/lighting/LightsNode.js +6 -27
- package/src/nodes/lighting/ShadowNode.js +24 -2
- package/src/nodes/math/BitcastNode.js +1 -1
- package/src/nodes/math/ConditionalNode.js +1 -1
- package/src/nodes/math/MathNode.js +73 -1
- package/src/nodes/math/OperatorNode.js +1 -1
- package/src/nodes/math/PackFloatNode.js +1 -1
- package/src/nodes/math/UnpackFloatNode.js +1 -1
- package/src/nodes/tsl/TSLBase.js +1 -1
- package/src/nodes/tsl/TSLCore.js +21 -3
- package/src/nodes/utils/ArrayElementNode.js +1 -1
- package/src/nodes/utils/ConvertNode.js +1 -1
- package/src/nodes/utils/DebugNode.js +1 -1
- package/src/nodes/utils/EventNode.js +30 -0
- package/src/nodes/utils/FlipNode.js +1 -1
- package/src/nodes/utils/FunctionOverloadingNode.js +1 -1
- package/src/nodes/utils/JoinNode.js +1 -1
- package/src/nodes/utils/MemberNode.js +1 -1
- package/src/nodes/utils/Remap.js +48 -0
- package/src/nodes/utils/RotateNode.js +1 -1
- package/src/nodes/utils/SetNode.js +1 -1
- package/src/nodes/utils/SplitNode.js +1 -1
- package/src/objects/BatchedMesh.js +17 -2
- package/src/objects/InstancedMesh.js +19 -3
- package/src/objects/SkinnedMesh.js +26 -9
- package/src/renderers/WebGLRenderer.js +148 -49
- package/src/renderers/common/Animation.js +3 -3
- package/src/renderers/common/Attributes.js +15 -1
- package/src/renderers/common/Backend.js +0 -8
- package/src/renderers/common/Background.js +2 -2
- package/src/renderers/common/BindGroup.js +1 -8
- package/src/renderers/common/Bindings.js +2 -2
- package/src/renderers/common/ComputePipeline.js +1 -1
- package/src/renderers/common/CubeRenderTarget.js +1 -1
- package/src/renderers/common/Info.js +333 -4
- package/src/renderers/common/InspectorBase.js +6 -1
- package/src/renderers/common/Pipelines.js +36 -3
- package/src/renderers/common/ReadbackBuffer.js +78 -0
- package/src/renderers/common/RenderBundle.js +3 -1
- package/src/renderers/common/RenderBundles.js +5 -2
- package/src/renderers/common/RenderObject.js +2 -2
- package/src/renderers/common/RenderObjects.js +3 -3
- package/src/renderers/common/RenderPipeline.js +35 -6
- package/src/renderers/common/Renderer.js +232 -53
- package/src/renderers/common/Textures.js +72 -3
- package/src/renderers/common/UniformsGroup.js +1 -1
- package/src/renderers/common/XRManager.js +34 -27
- package/src/renderers/common/extras/PMREMGenerator.js +23 -15
- package/src/renderers/common/nodes/NodeBuilderState.js +1 -1
- package/src/renderers/common/nodes/NodeManager.js +230 -99
- package/src/renderers/shaders/ShaderChunk/batching_pars_vertex.glsl.js +20 -0
- package/src/renderers/shaders/ShaderChunk/beginnormal_vertex.glsl.js +9 -1
- package/src/renderers/shaders/ShaderChunk/envmap_common_pars_fragment.glsl.js +0 -1
- package/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +1 -1
- package/src/renderers/shaders/ShaderChunk/lightprobes_pars_fragment.glsl.js +80 -0
- package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +8 -0
- package/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js +2 -0
- package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +1 -3
- package/src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl.js +7 -0
- package/src/renderers/shaders/ShaderChunk/premultiplied_alpha_fragment.glsl.js +0 -1
- package/src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js +12 -2
- package/src/renderers/shaders/ShaderChunk.js +2 -0
- package/src/renderers/shaders/ShaderLib/backgroundCube.glsl.js +1 -2
- package/src/renderers/shaders/ShaderLib.js +0 -1
- package/src/renderers/shaders/UniformsLib.js +7 -2
- package/src/renderers/shaders/UniformsUtils.js +27 -5
- package/src/renderers/webgl/WebGLAnimation.js +2 -1
- package/src/renderers/webgl/WebGLBackground.js +13 -13
- package/src/renderers/webgl/WebGLBufferRenderer.js +0 -32
- package/src/renderers/webgl/WebGLCapabilities.js +6 -0
- package/src/renderers/webgl/WebGLIndexedBufferRenderer.js +0 -32
- package/src/renderers/webgl/WebGLMaterials.js +12 -13
- package/src/renderers/webgl/WebGLOutput.js +4 -1
- package/src/renderers/webgl/WebGLProgram.js +5 -0
- package/src/renderers/webgl/WebGLPrograms.js +24 -3
- package/src/renderers/webgl/WebGLRenderStates.js +13 -2
- package/src/renderers/webgl/WebGLState.js +43 -0
- package/src/renderers/webgl/WebGLTextures.js +129 -26
- package/src/renderers/webgl/WebGLUniformsGroups.js +19 -0
- package/src/renderers/webgl-fallback/WebGLBackend.js +106 -65
- package/src/renderers/webgl-fallback/WebGLBufferRenderer.js +0 -41
- package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +29 -51
- package/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +53 -19
- package/src/renderers/webgl-fallback/utils/WebGLCapabilities.js +25 -0
- package/src/renderers/webgl-fallback/utils/WebGLState.js +42 -1
- package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +63 -50
- package/src/renderers/webgl-fallback/utils/WebGLTimestampQueryPool.js +1 -1
- package/src/renderers/webgpu/WebGPUBackend.js +160 -146
- package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +55 -33
- package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +103 -17
- package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +1 -1
- package/src/renderers/webgpu/utils/WebGPUCapabilities.js +48 -0
- package/src/renderers/webgpu/utils/WebGPUConstants.js +8 -0
- package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +91 -17
- package/src/renderers/webgpu/utils/WebGPUUtils.js +18 -2
- package/src/renderers/webxr/WebXRController.js +12 -0
- package/src/textures/HTMLTexture.js +74 -0
- package/src/textures/Source.js +1 -1
- package/src/textures/Texture.js +13 -2
- package/src/utils.js +23 -1
- package/src/nodes/utils/RemapNode.js +0 -125
|
@@ -601,7 +601,8 @@ class FBXTreeParser {
|
|
|
601
601
|
|
|
602
602
|
}
|
|
603
603
|
|
|
604
|
-
// the transparency handling is implemented based on Blender
|
|
604
|
+
// the transparency handling is implemented based on Blender's approach:
|
|
605
|
+
// https://github.com/blender/blender/blob/main/scripts/addons_core/io_scene_fbx/import_fbx.py
|
|
605
606
|
|
|
606
607
|
parameters.opacity = 1 - ( materialNode.TransparencyFactor ? parseFloat( materialNode.TransparencyFactor.value ) : 0 );
|
|
607
608
|
|
|
@@ -611,7 +612,10 @@ class FBXTreeParser {
|
|
|
611
612
|
|
|
612
613
|
if ( parameters.opacity === null ) {
|
|
613
614
|
|
|
614
|
-
|
|
615
|
+
// Default to opaque. Some exporters (e.g. 3ds Max) define TransparentColor
|
|
616
|
+
// as white (1,1,1) without intending transparency, which makes the Unity-style
|
|
617
|
+
// fallback of `1 - TransparentColor.r` produce incorrect zero opacity.
|
|
618
|
+
parameters.opacity = 1;
|
|
615
619
|
|
|
616
620
|
}
|
|
617
621
|
|
|
@@ -824,8 +828,6 @@ class FBXTreeParser {
|
|
|
824
828
|
indices: [],
|
|
825
829
|
weights: [],
|
|
826
830
|
transformLink: new Matrix4().fromArray( boneNode.TransformLink.a ),
|
|
827
|
-
// transform: new Matrix4().fromArray( boneNode.Transform.a ),
|
|
828
|
-
// linkMode: boneNode.Mode,
|
|
829
831
|
|
|
830
832
|
};
|
|
831
833
|
|
|
@@ -918,8 +920,6 @@ class FBXTreeParser {
|
|
|
918
920
|
|
|
919
921
|
} );
|
|
920
922
|
|
|
921
|
-
this.bindSkeleton( deformers.skeletons, geometryMap, modelMap );
|
|
922
|
-
|
|
923
923
|
this.addGlobalSceneSettings();
|
|
924
924
|
|
|
925
925
|
sceneGraph.traverse( function ( node ) {
|
|
@@ -942,6 +942,64 @@ class FBXTreeParser {
|
|
|
942
942
|
|
|
943
943
|
} );
|
|
944
944
|
|
|
945
|
+
// Like Blender's FBX importer, use the BindPose section to set the
|
|
946
|
+
// rest pose for bones that are not part of a skin cluster. The BindPose
|
|
947
|
+
// provides a more authoritative rest pose than the Lcl properties which
|
|
948
|
+
// may represent an animation frame rather than the true rest state.
|
|
949
|
+
// Bones WITH clusters will get their bind pose from TransformLink
|
|
950
|
+
// (set via bindSkeleton below), which takes priority.
|
|
951
|
+
const bindPoseMatrices = this.parsePoseNodes();
|
|
952
|
+
const clusterBoneIDs = new Set();
|
|
953
|
+
|
|
954
|
+
for ( const ID in deformers.skeletons ) {
|
|
955
|
+
|
|
956
|
+
deformers.skeletons[ ID ].rawBones.forEach( function ( _, i ) {
|
|
957
|
+
|
|
958
|
+
const bone = deformers.skeletons[ ID ].bones[ i ];
|
|
959
|
+
if ( bone ) clusterBoneIDs.add( bone.ID );
|
|
960
|
+
|
|
961
|
+
} );
|
|
962
|
+
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
const tempMatrix = new Matrix4();
|
|
966
|
+
|
|
967
|
+
sceneGraph.traverse( function ( node ) {
|
|
968
|
+
|
|
969
|
+
if ( node.isBone && node.ID !== undefined && ! clusterBoneIDs.has( node.ID ) ) {
|
|
970
|
+
|
|
971
|
+
const bindPose = bindPoseMatrices[ node.ID ];
|
|
972
|
+
|
|
973
|
+
if ( bindPose !== undefined ) {
|
|
974
|
+
|
|
975
|
+
if ( node.parent ) {
|
|
976
|
+
|
|
977
|
+
tempMatrix.copy( node.parent.matrixWorld ).invert();
|
|
978
|
+
tempMatrix.multiply( bindPose );
|
|
979
|
+
|
|
980
|
+
} else {
|
|
981
|
+
|
|
982
|
+
tempMatrix.copy( bindPose );
|
|
983
|
+
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
tempMatrix.decompose( node.position, node.quaternion, node.scale );
|
|
987
|
+
node.updateMatrix();
|
|
988
|
+
node.matrixWorld.copy( bindPose );
|
|
989
|
+
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
} );
|
|
995
|
+
|
|
996
|
+
// Bind skeletons after transforms are applied so that bind matrices
|
|
997
|
+
// are computed from the final scene state. This ensures the rest pose
|
|
998
|
+
// is correct even when the FBX file's Cluster TransformLink matrices
|
|
999
|
+
// differ from the reconstructed bone transforms (common in files
|
|
1000
|
+
// without a BindPose section).
|
|
1001
|
+
this.bindSkeleton( deformers.skeletons, geometryMap, modelMap );
|
|
1002
|
+
|
|
945
1003
|
const animations = new AnimationParser().parse();
|
|
946
1004
|
|
|
947
1005
|
// if all the models where already combined in a single group, just return that
|
|
@@ -954,6 +1012,24 @@ class FBXTreeParser {
|
|
|
954
1012
|
|
|
955
1013
|
sceneGraph.animations = animations;
|
|
956
1014
|
|
|
1015
|
+
// Apply coordinate system correction. FBX files can use different
|
|
1016
|
+
// up-axis conventions (Y-up or Z-up). Three.js uses Y-up, so rotate
|
|
1017
|
+
// the scene when the file uses Z-up (UpAxis === 2).
|
|
1018
|
+
|
|
1019
|
+
if ( 'GlobalSettings' in fbxTree && 'UpAxis' in fbxTree.GlobalSettings ) {
|
|
1020
|
+
|
|
1021
|
+
const upAxis = fbxTree.GlobalSettings.UpAxis.value;
|
|
1022
|
+
|
|
1023
|
+
if ( upAxis === 2 ) {
|
|
1024
|
+
|
|
1025
|
+
console.warn( 'THREE.FBXLoader: You are loading an asset with a Z-UP coordinate system. The loader just rotates the asset to transform it into Y-UP. The vertex data are not converted.' );
|
|
1026
|
+
|
|
1027
|
+
sceneGraph.rotation.set( - Math.PI / 2, 0, 0 );
|
|
1028
|
+
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
}
|
|
1032
|
+
|
|
957
1033
|
}
|
|
958
1034
|
|
|
959
1035
|
// parse nodes in FBXTree.Objects.Model
|
|
@@ -1236,21 +1312,24 @@ class FBXTreeParser {
|
|
|
1236
1312
|
|
|
1237
1313
|
case 2: // Spot
|
|
1238
1314
|
let angle = Math.PI / 3;
|
|
1315
|
+
let penumbra = 0;
|
|
1239
1316
|
|
|
1240
|
-
if ( lightAttribute.
|
|
1317
|
+
if ( lightAttribute.OuterAngle !== undefined ) {
|
|
1241
1318
|
|
|
1242
|
-
angle = MathUtils.degToRad( lightAttribute.
|
|
1319
|
+
angle = MathUtils.degToRad( lightAttribute.OuterAngle.value );
|
|
1243
1320
|
|
|
1244
|
-
|
|
1321
|
+
if ( lightAttribute.InnerAngle !== undefined ) {
|
|
1245
1322
|
|
|
1246
|
-
|
|
1247
|
-
|
|
1323
|
+
penumbra = 1 - ( lightAttribute.InnerAngle.value / lightAttribute.OuterAngle.value );
|
|
1324
|
+
penumbra = Math.max( 0, penumbra ); // penumbra must be in the range [0,1]
|
|
1248
1325
|
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
} else if ( lightAttribute.InnerAngle !== undefined ) {
|
|
1329
|
+
|
|
1330
|
+
// fallback if only InnerAngle is defined
|
|
1331
|
+
|
|
1332
|
+
angle = MathUtils.degToRad( lightAttribute.InnerAngle.value );
|
|
1254
1333
|
|
|
1255
1334
|
}
|
|
1256
1335
|
|
|
@@ -1460,12 +1539,30 @@ class FBXTreeParser {
|
|
|
1460
1539
|
|
|
1461
1540
|
bindSkeleton( skeletons, geometryMap, modelMap ) {
|
|
1462
1541
|
|
|
1463
|
-
const bindMatrices = this.parsePoseNodes();
|
|
1464
|
-
|
|
1465
1542
|
for ( const ID in skeletons ) {
|
|
1466
1543
|
|
|
1467
1544
|
const skeleton = skeletons[ ID ];
|
|
1468
1545
|
|
|
1546
|
+
// Compute bone inverses from TransformLink rather than from the
|
|
1547
|
+
// bones' current matrixWorld. The TransformLink matrices represent
|
|
1548
|
+
// each bone's global transform at the time the skin weights were
|
|
1549
|
+
// painted, which may differ from the scene-reconstructed transforms.
|
|
1550
|
+
const boneInverses = [];
|
|
1551
|
+
|
|
1552
|
+
for ( let i = 0, l = skeleton.bones.length; i < l; i ++ ) {
|
|
1553
|
+
|
|
1554
|
+
const inverse = new Matrix4();
|
|
1555
|
+
|
|
1556
|
+
if ( skeleton.bones[ i ] && skeleton.rawBones[ i ] ) {
|
|
1557
|
+
|
|
1558
|
+
inverse.copy( skeleton.rawBones[ i ].transformLink ).invert();
|
|
1559
|
+
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
boneInverses.push( inverse );
|
|
1563
|
+
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1469
1566
|
const parents = connections.get( parseInt( skeleton.ID ) ).parents;
|
|
1470
1567
|
|
|
1471
1568
|
parents.forEach( function ( parent ) {
|
|
@@ -1481,7 +1578,16 @@ class FBXTreeParser {
|
|
|
1481
1578
|
|
|
1482
1579
|
const model = modelMap.get( geoConnParent.ID );
|
|
1483
1580
|
|
|
1484
|
-
|
|
1581
|
+
// Use the mesh's current matrixWorld as bind matrix.
|
|
1582
|
+
// The BindPose section is intentionally not used here
|
|
1583
|
+
// since it may contain scale/rotation from the model
|
|
1584
|
+
// hierarchy that is inconsistent with the TransformLink-
|
|
1585
|
+
// based bone inverses. Always provide a bind matrix to
|
|
1586
|
+
// prevent bind() from calling calculateInverses() which
|
|
1587
|
+
// would overwrite the bone inverses computed above.
|
|
1588
|
+
model.updateMatrixWorld( true );
|
|
1589
|
+
|
|
1590
|
+
model.bind( new Skeleton( skeleton.bones, boneInverses ), model.matrixWorld );
|
|
1485
1591
|
|
|
1486
1592
|
}
|
|
1487
1593
|
|
|
@@ -1495,6 +1601,7 @@ class FBXTreeParser {
|
|
|
1495
1601
|
|
|
1496
1602
|
}
|
|
1497
1603
|
|
|
1604
|
+
// Parse BindPose nodes and return a map of node ID to bind matrix.
|
|
1498
1605
|
parsePoseNodes() {
|
|
1499
1606
|
|
|
1500
1607
|
const bindMatrices = {};
|
|
@@ -2257,6 +2364,13 @@ class GeometryParser {
|
|
|
2257
2364
|
parentGeo.morphAttributes.position = [];
|
|
2258
2365
|
// parentGeo.morphAttributes.normal = []; // not implemented
|
|
2259
2366
|
|
|
2367
|
+
// Morph attribute positions are stored as deltas (morphTargetsRelative = true), so the
|
|
2368
|
+
// translation component of the geometric transform must not be applied to them — only the
|
|
2369
|
+
// rotation/scale part. Otherwise every delta gets the geometric translation added, which
|
|
2370
|
+
// shifts morphed vertices away from their intended position by `weight * translation` as
|
|
2371
|
+
// the influence increases.
|
|
2372
|
+
const morphPreTransform = preTransform.clone().setPosition( 0, 0, 0 );
|
|
2373
|
+
|
|
2260
2374
|
const scope = this;
|
|
2261
2375
|
morphTargets.forEach( function ( morphTarget ) {
|
|
2262
2376
|
|
|
@@ -2266,7 +2380,7 @@ class GeometryParser {
|
|
|
2266
2380
|
|
|
2267
2381
|
if ( morphGeoNode !== undefined ) {
|
|
2268
2382
|
|
|
2269
|
-
scope.genMorphGeometry( parentGeo, parentGeoNode, morphGeoNode,
|
|
2383
|
+
scope.genMorphGeometry( parentGeo, parentGeoNode, morphGeoNode, morphPreTransform, rawTarget.name );
|
|
2270
2384
|
|
|
2271
2385
|
}
|
|
2272
2386
|
|
|
@@ -2661,11 +2775,15 @@ class AnimationParser {
|
|
|
2661
2775
|
|
|
2662
2776
|
if ( layerCurveNodes[ i ] === undefined ) {
|
|
2663
2777
|
|
|
2664
|
-
const
|
|
2778
|
+
const filteredParents = connections.get( child.ID ).parents.filter( function ( parent ) {
|
|
2665
2779
|
|
|
2666
2780
|
return parent.relationship !== undefined;
|
|
2667
2781
|
|
|
2668
|
-
} )
|
|
2782
|
+
} );
|
|
2783
|
+
|
|
2784
|
+
if ( filteredParents.length === 0 ) return;
|
|
2785
|
+
|
|
2786
|
+
const modelID = filteredParents[ 0 ].ID;
|
|
2669
2787
|
|
|
2670
2788
|
if ( modelID !== undefined ) {
|
|
2671
2789
|
|
|
@@ -2694,7 +2812,13 @@ class AnimationParser {
|
|
|
2694
2812
|
|
|
2695
2813
|
node.transform = child.matrix;
|
|
2696
2814
|
|
|
2697
|
-
if ( child.userData.transformData )
|
|
2815
|
+
if ( child.userData.transformData ) {
|
|
2816
|
+
|
|
2817
|
+
node.eulerOrder = child.userData.transformData.eulerOrder;
|
|
2818
|
+
|
|
2819
|
+
if ( child.userData.transformData.rotation ) node.initialRotation = child.userData.transformData.rotation;
|
|
2820
|
+
|
|
2821
|
+
}
|
|
2698
2822
|
|
|
2699
2823
|
}
|
|
2700
2824
|
|
|
@@ -2719,11 +2843,15 @@ class AnimationParser {
|
|
|
2719
2843
|
|
|
2720
2844
|
if ( layerCurveNodes[ i ] === undefined ) {
|
|
2721
2845
|
|
|
2722
|
-
const
|
|
2846
|
+
const filteredParents = connections.get( child.ID ).parents.filter( function ( parent ) {
|
|
2723
2847
|
|
|
2724
2848
|
return parent.relationship !== undefined;
|
|
2725
2849
|
|
|
2726
|
-
} )
|
|
2850
|
+
} );
|
|
2851
|
+
|
|
2852
|
+
if ( filteredParents.length === 0 ) return;
|
|
2853
|
+
|
|
2854
|
+
const deformerID = filteredParents[ 0 ].ID;
|
|
2727
2855
|
|
|
2728
2856
|
const morpherID = connections.get( deformerID ).parents[ 0 ].ID;
|
|
2729
2857
|
const geoID = connections.get( morpherID ).parents[ 0 ].ID;
|
|
@@ -2834,7 +2962,7 @@ class AnimationParser {
|
|
|
2834
2962
|
|
|
2835
2963
|
if ( rawTracks.R !== undefined && Object.keys( rawTracks.R.curves ).length > 0 ) {
|
|
2836
2964
|
|
|
2837
|
-
const rotationTrack = this.generateRotationTrack( rawTracks.modelName, rawTracks.R.curves, rawTracks.preRotation, rawTracks.postRotation, rawTracks.eulerOrder );
|
|
2965
|
+
const rotationTrack = this.generateRotationTrack( rawTracks.modelName, rawTracks.R.curves, rawTracks.preRotation, rawTracks.postRotation, rawTracks.eulerOrder, rawTracks.initialRotation );
|
|
2838
2966
|
if ( rotationTrack !== undefined ) tracks.push( rotationTrack );
|
|
2839
2967
|
|
|
2840
2968
|
}
|
|
@@ -2866,17 +2994,33 @@ class AnimationParser {
|
|
|
2866
2994
|
|
|
2867
2995
|
}
|
|
2868
2996
|
|
|
2869
|
-
generateRotationTrack( modelName, curves, preRotation, postRotation, eulerOrder ) {
|
|
2997
|
+
generateRotationTrack( modelName, curves, preRotation, postRotation, eulerOrder, initialRotation ) {
|
|
2870
2998
|
|
|
2871
2999
|
let times;
|
|
2872
3000
|
let values;
|
|
2873
3001
|
|
|
2874
|
-
if ( curves.x !== undefined
|
|
3002
|
+
if ( curves.x !== undefined || curves.y !== undefined || curves.z !== undefined ) {
|
|
3003
|
+
|
|
3004
|
+
// Get merged, sorted, unique times from all available curves
|
|
3005
|
+
const mergedTimes = this.getTimesForAllAxes( curves );
|
|
3006
|
+
|
|
3007
|
+
if ( mergedTimes.length > 0 ) {
|
|
3008
|
+
|
|
3009
|
+
const initialRot = initialRotation || [ 0, 0, 0 ];
|
|
2875
3010
|
|
|
2876
|
-
|
|
3011
|
+
// Synchronize all curves to the merged time array.
|
|
3012
|
+
// Missing axes are filled with constant values from the initial rotation (Lcl Rotation).
|
|
3013
|
+
// Existing curves at different times are linearly interpolated.
|
|
3014
|
+
const syncX = this.synchronizeCurve( curves.x, mergedTimes, initialRot[ 0 ] );
|
|
3015
|
+
const syncY = this.synchronizeCurve( curves.y, mergedTimes, initialRot[ 1 ] );
|
|
3016
|
+
const syncZ = this.synchronizeCurve( curves.z, mergedTimes, initialRot[ 2 ] );
|
|
2877
3017
|
|
|
2878
|
-
|
|
2879
|
-
|
|
3018
|
+
const result = this.interpolateRotations( syncX, syncY, syncZ, eulerOrder );
|
|
3019
|
+
|
|
3020
|
+
times = result[ 0 ];
|
|
3021
|
+
values = result[ 1 ];
|
|
3022
|
+
|
|
3023
|
+
}
|
|
2880
3024
|
|
|
2881
3025
|
}
|
|
2882
3026
|
|
|
@@ -2908,7 +3052,7 @@ class AnimationParser {
|
|
|
2908
3052
|
|
|
2909
3053
|
const quaternionValues = [];
|
|
2910
3054
|
|
|
2911
|
-
if ( ! values || ! times ) return
|
|
3055
|
+
if ( ! values || ! times ) return undefined;
|
|
2912
3056
|
|
|
2913
3057
|
for ( let i = 0; i < values.length; i += 3 ) {
|
|
2914
3058
|
|
|
@@ -3061,6 +3205,62 @@ class AnimationParser {
|
|
|
3061
3205
|
|
|
3062
3206
|
}
|
|
3063
3207
|
|
|
3208
|
+
// Synchronize a curve to a target time array using linear interpolation.
|
|
3209
|
+
// If the curve is undefined (axis not animated), returns constant values from initialValue.
|
|
3210
|
+
synchronizeCurve( curve, targetTimes, initialValue ) {
|
|
3211
|
+
|
|
3212
|
+
if ( curve === undefined ) {
|
|
3213
|
+
|
|
3214
|
+
return { times: targetTimes, values: targetTimes.map( () => initialValue ) };
|
|
3215
|
+
|
|
3216
|
+
}
|
|
3217
|
+
|
|
3218
|
+
// If the curve already has the same number of keyframes as the target, assume times match
|
|
3219
|
+
if ( curve.times.length === targetTimes.length ) return curve;
|
|
3220
|
+
|
|
3221
|
+
// Linearly interpolate curve values at each target time
|
|
3222
|
+
const values = [];
|
|
3223
|
+
|
|
3224
|
+
for ( let i = 0; i < targetTimes.length; i ++ ) {
|
|
3225
|
+
|
|
3226
|
+
values.push( this.sampleCurveValue( curve, targetTimes[ i ], initialValue ) );
|
|
3227
|
+
|
|
3228
|
+
}
|
|
3229
|
+
|
|
3230
|
+
return { times: targetTimes, values: values };
|
|
3231
|
+
|
|
3232
|
+
}
|
|
3233
|
+
|
|
3234
|
+
// Sample a single value from a curve at a given time using linear interpolation
|
|
3235
|
+
sampleCurveValue( curve, time, initialValue ) {
|
|
3236
|
+
|
|
3237
|
+
const times = curve.times;
|
|
3238
|
+
const values = curve.values;
|
|
3239
|
+
|
|
3240
|
+
// Before first keyframe
|
|
3241
|
+
if ( time <= times[ 0 ] ) return values[ 0 ];
|
|
3242
|
+
|
|
3243
|
+
// After last keyframe
|
|
3244
|
+
if ( time >= times[ times.length - 1 ] ) return values[ values.length - 1 ];
|
|
3245
|
+
|
|
3246
|
+
// Find surrounding keyframes and linearly interpolate
|
|
3247
|
+
for ( let i = 0; i < times.length - 1; i ++ ) {
|
|
3248
|
+
|
|
3249
|
+
if ( time >= times[ i ] && time <= times[ i + 1 ] ) {
|
|
3250
|
+
|
|
3251
|
+
if ( times[ i ] === time ) return values[ i ];
|
|
3252
|
+
|
|
3253
|
+
const alpha = ( time - times[ i ] ) / ( times[ i + 1 ] - times[ i ] );
|
|
3254
|
+
return values[ i ] * ( 1 - alpha ) + values[ i + 1 ] * alpha;
|
|
3255
|
+
|
|
3256
|
+
}
|
|
3257
|
+
|
|
3258
|
+
}
|
|
3259
|
+
|
|
3260
|
+
return initialValue;
|
|
3261
|
+
|
|
3262
|
+
}
|
|
3263
|
+
|
|
3064
3264
|
// Rotations are defined as Euler angles which can have values of any size
|
|
3065
3265
|
// These will be converted to quaternions which don't support values greater than
|
|
3066
3266
|
// PI, so we'll interpolate large rotations
|
|
@@ -3130,7 +3330,7 @@ class AnimationParser {
|
|
|
3130
3330
|
const Q2 = new Quaternion().setFromEuler( E2 );
|
|
3131
3331
|
|
|
3132
3332
|
// Check unroll
|
|
3133
|
-
if ( Q1.dot( Q2 ) ) {
|
|
3333
|
+
if ( Q1.dot( Q2 ) < 0 ) {
|
|
3134
3334
|
|
|
3135
3335
|
Q2.set( - Q2.x, - Q2.y, - Q2.z, - Q2.w );
|
|
3136
3336
|
|
|
@@ -83,8 +83,11 @@ import { clone } from '../utils/SkeletonUtils.js';
|
|
|
83
83
|
*
|
|
84
84
|
* `GLTFLoader` supports the following glTF 2.0 extensions:
|
|
85
85
|
* - KHR_draco_mesh_compression
|
|
86
|
+
* - KHR_lights_punctual
|
|
87
|
+
* - KHR_materials_anisotropy
|
|
86
88
|
* - KHR_materials_clearcoat
|
|
87
89
|
* - KHR_materials_dispersion
|
|
90
|
+
* - KHR_materials_emissive_strength
|
|
88
91
|
* - KHR_materials_ior
|
|
89
92
|
* - KHR_materials_specular
|
|
90
93
|
* - KHR_materials_transmission
|
|
@@ -93,12 +96,13 @@ import { clone } from '../utils/SkeletonUtils.js';
|
|
|
93
96
|
* - KHR_materials_volume
|
|
94
97
|
* - KHR_mesh_quantization
|
|
95
98
|
* - KHR_meshopt_compression
|
|
96
|
-
* - KHR_lights_punctual
|
|
97
99
|
* - KHR_texture_basisu
|
|
98
100
|
* - KHR_texture_transform
|
|
99
|
-
* -
|
|
101
|
+
* - EXT_materials_bump
|
|
100
102
|
* - EXT_meshopt_compression
|
|
101
103
|
* - EXT_mesh_gpu_instancing
|
|
104
|
+
* - EXT_texture_avif
|
|
105
|
+
* - EXT_texture_webp
|
|
102
106
|
*
|
|
103
107
|
* The following glTF 2.0 extension is supported by an external user plugin:
|
|
104
108
|
* - [KHR_materials_variants](https://github.com/takahirox/three-gltf-extensions)
|
|
@@ -1269,6 +1273,8 @@ class GLTFMaterialsIorExtension {
|
|
|
1269
1273
|
|
|
1270
1274
|
materialParams.ior = extension.ior !== undefined ? extension.ior : 1.5;
|
|
1271
1275
|
|
|
1276
|
+
if ( materialParams.ior === 0 ) materialParams.ior = 1000; // see #26167
|
|
1277
|
+
|
|
1272
1278
|
return Promise.resolve();
|
|
1273
1279
|
|
|
1274
1280
|
}
|
|
@@ -4512,17 +4518,28 @@ class GLTFParser {
|
|
|
4512
4518
|
const targetName = node.name ? node.name : node.uuid;
|
|
4513
4519
|
const targetNames = [];
|
|
4514
4520
|
|
|
4521
|
+
function collectMorphTargets( object ) {
|
|
4522
|
+
|
|
4523
|
+
if ( object.morphTargetInfluences ) {
|
|
4524
|
+
|
|
4525
|
+
targetNames.push( object.name ? object.name : object.uuid );
|
|
4526
|
+
|
|
4527
|
+
}
|
|
4528
|
+
|
|
4529
|
+
}
|
|
4530
|
+
|
|
4531
|
+
|
|
4515
4532
|
if ( PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.weights ) {
|
|
4516
4533
|
|
|
4517
|
-
|
|
4534
|
+
collectMorphTargets( node );
|
|
4518
4535
|
|
|
4519
|
-
|
|
4536
|
+
// for multi-primitive meshes, the node is a Group containing the sub-meshes
|
|
4520
4537
|
|
|
4521
|
-
|
|
4538
|
+
if ( node.isGroup ) {
|
|
4522
4539
|
|
|
4523
|
-
|
|
4540
|
+
node.children.forEach( collectMorphTargets );
|
|
4524
4541
|
|
|
4525
|
-
}
|
|
4542
|
+
}
|
|
4526
4543
|
|
|
4527
4544
|
} else {
|
|
4528
4545
|
|
|
@@ -100,7 +100,7 @@ class HDRLoader extends DataTextureLoader {
|
|
|
100
100
|
|
|
101
101
|
s += chunk; len += chunk.length;
|
|
102
102
|
p += chunkSize;
|
|
103
|
-
chunk
|
|
103
|
+
chunk = String.fromCharCode.apply( null, new Uint16Array( buffer.subarray( p, p + chunkSize ) ) );
|
|
104
104
|
|
|
105
105
|
}
|
|
106
106
|
|
|
@@ -42,7 +42,8 @@ import {
|
|
|
42
42
|
SRGBColorSpace,
|
|
43
43
|
UnsignedByteType,
|
|
44
44
|
UnsignedInt5999Type,
|
|
45
|
-
UnsignedInt101111Type
|
|
45
|
+
UnsignedInt101111Type,
|
|
46
|
+
UnsignedShortType
|
|
46
47
|
} from 'three';
|
|
47
48
|
import { WorkerPool } from '../utils/WorkerPool.js';
|
|
48
49
|
import {
|
|
@@ -83,6 +84,7 @@ import {
|
|
|
83
84
|
VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG,
|
|
84
85
|
VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG,
|
|
85
86
|
VK_FORMAT_R16G16B16A16_SFLOAT,
|
|
87
|
+
VK_FORMAT_R16G16B16A16_UNORM,
|
|
86
88
|
VK_FORMAT_R16G16_SFLOAT,
|
|
87
89
|
VK_FORMAT_R16_SFLOAT,
|
|
88
90
|
VK_FORMAT_R32G32B32A32_SFLOAT,
|
|
@@ -964,6 +966,8 @@ const FORMAT_MAP = {
|
|
|
964
966
|
[ VK_FORMAT_R16G16_SFLOAT ]: RGFormat,
|
|
965
967
|
[ VK_FORMAT_R16_SFLOAT ]: RedFormat,
|
|
966
968
|
|
|
969
|
+
[ VK_FORMAT_R16G16B16A16_UNORM ]: RGBAFormat,
|
|
970
|
+
|
|
967
971
|
[ VK_FORMAT_R8G8B8A8_SRGB ]: RGBAFormat,
|
|
968
972
|
[ VK_FORMAT_R8G8B8A8_UNORM ]: RGBAFormat,
|
|
969
973
|
[ VK_FORMAT_R8G8_SRGB ]: RGFormat,
|
|
@@ -1022,6 +1026,8 @@ const TYPE_MAP = {
|
|
|
1022
1026
|
[ VK_FORMAT_R16G16_SFLOAT ]: HalfFloatType,
|
|
1023
1027
|
[ VK_FORMAT_R16_SFLOAT ]: HalfFloatType,
|
|
1024
1028
|
|
|
1029
|
+
[ VK_FORMAT_R16G16B16A16_UNORM ]: UnsignedShortType,
|
|
1030
|
+
|
|
1025
1031
|
[ VK_FORMAT_R8G8B8A8_SRGB ]: UnsignedByteType,
|
|
1026
1032
|
[ VK_FORMAT_R8G8B8A8_UNORM ]: UnsignedByteType,
|
|
1027
1033
|
[ VK_FORMAT_R8G8_SRGB ]: UnsignedByteType,
|
|
@@ -1149,7 +1155,7 @@ async function createRawTexture( container ) {
|
|
|
1149
1155
|
|
|
1150
1156
|
);
|
|
1151
1157
|
|
|
1152
|
-
} else if ( TYPE_MAP[ vkFormat ] === HalfFloatType ) {
|
|
1158
|
+
} else if ( TYPE_MAP[ vkFormat ] === HalfFloatType || TYPE_MAP[ vkFormat ] === UnsignedShortType ) {
|
|
1153
1159
|
|
|
1154
1160
|
data = new Uint16Array(
|
|
1155
1161
|
|
|
@@ -1015,21 +1015,9 @@ class LDrawParsedCache {
|
|
|
1015
1015
|
faceNormal: null,
|
|
1016
1016
|
vertices: [ v0, v1, v2 ],
|
|
1017
1017
|
normals: [ null, null, null ],
|
|
1018
|
+
doubleSided: doubleSided,
|
|
1018
1019
|
} );
|
|
1019
|
-
totalFaces
|
|
1020
|
-
|
|
1021
|
-
if ( doubleSided === true ) {
|
|
1022
|
-
|
|
1023
|
-
faces.push( {
|
|
1024
|
-
material: material,
|
|
1025
|
-
colorCode: colorCode,
|
|
1026
|
-
faceNormal: null,
|
|
1027
|
-
vertices: [ v2, v1, v0 ],
|
|
1028
|
-
normals: [ null, null, null ],
|
|
1029
|
-
} );
|
|
1030
|
-
totalFaces ++;
|
|
1031
|
-
|
|
1032
|
-
}
|
|
1020
|
+
totalFaces += doubleSided ? 2 : 1;
|
|
1033
1021
|
|
|
1034
1022
|
break;
|
|
1035
1023
|
|
|
@@ -1065,21 +1053,9 @@ class LDrawParsedCache {
|
|
|
1065
1053
|
faceNormal: null,
|
|
1066
1054
|
vertices: [ v0, v1, v2, v3 ],
|
|
1067
1055
|
normals: [ null, null, null, null ],
|
|
1056
|
+
doubleSided: doubleSided,
|
|
1068
1057
|
} );
|
|
1069
|
-
totalFaces += 2;
|
|
1070
|
-
|
|
1071
|
-
if ( doubleSided === true ) {
|
|
1072
|
-
|
|
1073
|
-
faces.push( {
|
|
1074
|
-
material: material,
|
|
1075
|
-
colorCode: colorCode,
|
|
1076
|
-
faceNormal: null,
|
|
1077
|
-
vertices: [ v3, v2, v1, v0 ],
|
|
1078
|
-
normals: [ null, null, null, null ],
|
|
1079
|
-
} );
|
|
1080
|
-
totalFaces += 2;
|
|
1081
|
-
|
|
1082
|
-
}
|
|
1058
|
+
totalFaces += doubleSided ? 4 : 2;
|
|
1083
1059
|
|
|
1084
1060
|
break;
|
|
1085
1061
|
|
|
@@ -1550,13 +1526,22 @@ function createObject( loader, elements, elementSize, isConditionalSegments = fa
|
|
|
1550
1526
|
|
|
1551
1527
|
}
|
|
1552
1528
|
|
|
1553
|
-
|
|
1529
|
+
const sideCount = elementSize === 3 && elem.doubleSided ? 2 : 1;
|
|
1530
|
+
const sideVertCount = vertices.length;
|
|
1531
|
+
const totalVertCount = sideVertCount * sideCount;
|
|
1554
1532
|
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1533
|
+
for ( let s = 0; s < sideCount; s ++ ) {
|
|
1534
|
+
|
|
1535
|
+
for ( let j = 0; j < sideVertCount; j ++ ) {
|
|
1536
|
+
|
|
1537
|
+
// front side: original order; back side: reversed winding
|
|
1538
|
+
const v = vertices[ s === 0 ? j : sideVertCount - 1 - j ];
|
|
1539
|
+
const index = offset + ( s * sideVertCount + j ) * 3;
|
|
1540
|
+
positions[ index + 0 ] = v.x;
|
|
1541
|
+
positions[ index + 1 ] = v.y;
|
|
1542
|
+
positions[ index + 2 ] = v.z;
|
|
1543
|
+
|
|
1544
|
+
}
|
|
1560
1545
|
|
|
1561
1546
|
}
|
|
1562
1547
|
|
|
@@ -1589,20 +1574,27 @@ function createObject( loader, elements, elementSize, isConditionalSegments = fa
|
|
|
1589
1574
|
|
|
1590
1575
|
}
|
|
1591
1576
|
|
|
1592
|
-
|
|
1577
|
+
const normalCount = elemNormals.length;
|
|
1578
|
+
for ( let s = 0; s < sideCount; s ++ ) {
|
|
1593
1579
|
|
|
1594
|
-
|
|
1595
|
-
let
|
|
1596
|
-
if ( elemNormals[ j ] ) {
|
|
1580
|
+
const sign = s === 0 ? 1 : - 1;
|
|
1581
|
+
for ( let j = 0; j < normalCount; j ++ ) {
|
|
1597
1582
|
|
|
1598
|
-
|
|
1583
|
+
// back side reuses the front normals in reversed order, with negated direction
|
|
1584
|
+
const idx = s === 0 ? j : normalCount - 1 - j;
|
|
1585
|
+
let n = elem.faceNormal;
|
|
1586
|
+
if ( elemNormals[ idx ] ) {
|
|
1599
1587
|
|
|
1600
|
-
|
|
1588
|
+
n = elemNormals[ idx ].norm;
|
|
1601
1589
|
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
const index = offset + ( s * normalCount + j ) * 3;
|
|
1593
|
+
normals[ index + 0 ] = sign * n.x;
|
|
1594
|
+
normals[ index + 1 ] = sign * n.y;
|
|
1595
|
+
normals[ index + 2 ] = sign * n.z;
|
|
1596
|
+
|
|
1597
|
+
}
|
|
1606
1598
|
|
|
1607
1599
|
}
|
|
1608
1600
|
|
|
@@ -1650,15 +1642,15 @@ function createObject( loader, elements, elementSize, isConditionalSegments = fa
|
|
|
1650
1642
|
|
|
1651
1643
|
prevMaterial = elem.colorCode;
|
|
1652
1644
|
index0 = offset / 3;
|
|
1653
|
-
numGroupVerts =
|
|
1645
|
+
numGroupVerts = totalVertCount;
|
|
1654
1646
|
|
|
1655
1647
|
} else {
|
|
1656
1648
|
|
|
1657
|
-
numGroupVerts +=
|
|
1649
|
+
numGroupVerts += totalVertCount;
|
|
1658
1650
|
|
|
1659
1651
|
}
|
|
1660
1652
|
|
|
1661
|
-
offset += 3 *
|
|
1653
|
+
offset += 3 * totalVertCount;
|
|
1662
1654
|
|
|
1663
1655
|
}
|
|
1664
1656
|
|