@needle-tools/three 0.154.2 → 0.160.2

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.
Files changed (957) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +86 -84
  3. package/build/three.cjs +53679 -51654
  4. package/build/three.module.js +53263 -51253
  5. package/build/three.module.min.js +6 -6
  6. package/examples/fonts/LICENSE +13 -13
  7. package/examples/fonts/README.md +11 -11
  8. package/examples/fonts/droid/NOTICE +190 -190
  9. package/examples/fonts/droid/README.txt +18 -18
  10. package/examples/fonts/ttf/README.md +9 -9
  11. package/examples/jsm/Addons.js +294 -0
  12. package/examples/jsm/animation/AnimationClipCreator.js +116 -116
  13. package/examples/jsm/animation/CCDIKSolver.js +482 -482
  14. package/examples/jsm/animation/MMDAnimationHelper.js +1207 -1207
  15. package/examples/jsm/animation/MMDPhysics.js +1406 -1406
  16. package/examples/jsm/cameras/CinematicCamera.js +208 -208
  17. package/examples/jsm/capabilities/WebGL.js +108 -91
  18. package/examples/jsm/capabilities/WebGPU.js +57 -53
  19. package/examples/jsm/controls/ArcballControls.js +3224 -3224
  20. package/examples/jsm/controls/DragControls.js +221 -220
  21. package/examples/jsm/controls/FirstPersonControls.js +325 -325
  22. package/examples/jsm/controls/FlyControls.js +326 -300
  23. package/examples/jsm/controls/MapControls.js +28 -28
  24. package/examples/jsm/controls/OrbitControls.js +1521 -1279
  25. package/examples/jsm/controls/PointerLockControls.js +162 -162
  26. package/examples/jsm/controls/TrackballControls.js +828 -828
  27. package/examples/jsm/controls/TransformControls.js +1573 -1557
  28. package/examples/jsm/csm/CSM.js +384 -384
  29. package/examples/jsm/csm/CSMFrustum.js +152 -152
  30. package/examples/jsm/csm/CSMHelper.js +193 -193
  31. package/examples/jsm/csm/CSMShader.js +295 -252
  32. package/examples/jsm/curves/CurveExtras.js +422 -422
  33. package/examples/jsm/curves/NURBSCurve.js +80 -80
  34. package/examples/jsm/curves/NURBSSurface.js +52 -52
  35. package/examples/jsm/curves/NURBSUtils.js +487 -487
  36. package/examples/jsm/effects/AnaglyphEffect.js +154 -154
  37. package/examples/jsm/effects/AsciiEffect.js +263 -263
  38. package/examples/jsm/effects/OutlineEffect.js +539 -539
  39. package/examples/jsm/effects/ParallaxBarrierEffect.js +119 -119
  40. package/examples/jsm/effects/PeppersGhostEffect.js +153 -153
  41. package/examples/jsm/effects/StereoEffect.js +55 -55
  42. package/examples/jsm/environments/DebugEnvironment.js +52 -52
  43. package/examples/jsm/environments/RoomEnvironment.js +148 -148
  44. package/examples/jsm/exporters/DRACOExporter.js +267 -267
  45. package/examples/jsm/exporters/EXRExporter.js +579 -501
  46. package/examples/jsm/exporters/GLTFExporter.js +3311 -3163
  47. package/examples/jsm/exporters/KTX2Exporter.js +292 -292
  48. package/examples/jsm/exporters/MMDExporter.js +217 -217
  49. package/examples/jsm/exporters/OBJExporter.js +284 -284
  50. package/examples/jsm/exporters/PLYExporter.js +528 -528
  51. package/examples/jsm/exporters/STLExporter.js +199 -199
  52. package/examples/jsm/exporters/USDZExporter.js +720 -710
  53. package/examples/jsm/geometries/BoxLineGeometry.js +69 -69
  54. package/examples/jsm/geometries/ConvexGeometry.js +53 -53
  55. package/examples/jsm/geometries/DecalGeometry.js +356 -356
  56. package/examples/jsm/geometries/InstancedPointsGeometry.js +174 -0
  57. package/examples/jsm/geometries/ParametricGeometries.js +254 -254
  58. package/examples/jsm/geometries/ParametricGeometry.js +139 -139
  59. package/examples/jsm/geometries/RoundedBoxGeometry.js +155 -155
  60. package/examples/jsm/geometries/SDFGeometryGenerator.js +144 -0
  61. package/examples/jsm/geometries/TeapotGeometry.js +704 -704
  62. package/examples/jsm/geometries/TextGeometry.js +57 -57
  63. package/examples/jsm/helpers/LightProbeHelper.js +130 -130
  64. package/examples/jsm/helpers/OctreeHelper.js +73 -73
  65. package/examples/jsm/helpers/PositionalAudioHelper.js +109 -109
  66. package/examples/jsm/helpers/RectAreaLightHelper.js +85 -85
  67. package/examples/jsm/helpers/TextureHelper.js +237 -0
  68. package/examples/jsm/helpers/VertexNormalsHelper.js +96 -96
  69. package/examples/jsm/helpers/VertexTangentsHelper.js +88 -88
  70. package/examples/jsm/helpers/ViewHelper.js +333 -333
  71. package/examples/jsm/interactive/HTMLMesh.js +572 -565
  72. package/examples/jsm/interactive/InteractiveGroup.js +116 -116
  73. package/examples/jsm/interactive/SelectionBox.js +227 -227
  74. package/examples/jsm/interactive/SelectionHelper.js +104 -97
  75. package/examples/jsm/libs/ammo.wasm.js +822 -822
  76. package/examples/jsm/libs/basis/README.md +46 -46
  77. package/examples/jsm/libs/basis/basis_transcoder.js +21 -21
  78. package/examples/jsm/libs/chevrotain.module.min.js +141 -141
  79. package/examples/jsm/libs/draco/README.md +32 -32
  80. package/examples/jsm/libs/draco/draco_decoder.js +34 -34
  81. package/examples/jsm/libs/draco/draco_encoder.js +33 -33
  82. package/examples/jsm/libs/draco/draco_wasm_wrapper.js +117 -117
  83. package/examples/jsm/libs/draco/gltf/draco_decoder.js +33 -33
  84. package/examples/jsm/libs/draco/gltf/draco_encoder.js +33 -33
  85. package/examples/jsm/libs/draco/gltf/draco_wasm_wrapper.js +116 -116
  86. package/examples/jsm/libs/ecsy.module.js +1792 -1792
  87. package/examples/jsm/libs/fflate.module.js +2474 -2474
  88. package/examples/jsm/libs/ktx-parse.module.js +1 -1
  89. package/examples/jsm/libs/lil-gui.module.min.js +8 -8
  90. package/examples/jsm/libs/lottie_canvas.module.js +14849 -14844
  91. package/examples/jsm/libs/meshopt_decoder.module.js +178 -178
  92. package/examples/jsm/libs/mikktspace.module.js +128 -128
  93. package/examples/jsm/libs/mmdparser.module.js +11530 -11530
  94. package/examples/jsm/libs/motion-controllers.module.js +397 -397
  95. package/examples/jsm/libs/opentype.module.js +14506 -14568
  96. package/examples/jsm/libs/potpack.module.js +124 -124
  97. package/examples/jsm/libs/rhino3dm/rhino3dm.js +8743 -21
  98. package/examples/jsm/libs/rhino3dm/rhino3dm.module.js +8748 -15
  99. package/examples/jsm/libs/rhino3dm/rhino3dm.wasm +0 -0
  100. package/examples/jsm/libs/stats.module.js +167 -167
  101. package/examples/jsm/libs/surfaceNet.js +201 -0
  102. package/examples/jsm/libs/tween.module.js +858 -803
  103. package/examples/jsm/libs/utif.module.js +1664 -1578
  104. package/examples/jsm/libs/zstddec.module.js +1 -1
  105. package/examples/jsm/lights/IESSpotLight.js +25 -25
  106. package/examples/jsm/lights/LightProbeGenerator.js +286 -252
  107. package/examples/jsm/lights/RectAreaLightUniformsLib.js +79 -79
  108. package/examples/jsm/lines/Line2.js +19 -19
  109. package/examples/jsm/lines/LineGeometry.js +79 -79
  110. package/examples/jsm/lines/LineMaterial.js +619 -702
  111. package/examples/jsm/lines/LineSegments2.js +361 -361
  112. package/examples/jsm/lines/LineSegmentsGeometry.js +241 -241
  113. package/examples/jsm/lines/Wireframe.js +56 -56
  114. package/examples/jsm/lines/WireframeGeometry2.js +24 -24
  115. package/examples/jsm/loaders/3DMLoader.js +1772 -1497
  116. package/examples/jsm/loaders/3MFLoader.js +1478 -1478
  117. package/examples/jsm/loaders/AMFLoader.js +521 -521
  118. package/examples/jsm/loaders/BVHLoader.js +437 -437
  119. package/examples/jsm/loaders/ColladaLoader.js +4116 -4122
  120. package/examples/jsm/loaders/DDSLoader.js +318 -274
  121. package/examples/jsm/loaders/DRACOLoader.js +613 -612
  122. package/examples/jsm/loaders/EXRLoader.js +2309 -2309
  123. package/examples/jsm/loaders/FBXLoader.js +4314 -4142
  124. package/examples/jsm/loaders/FontLoader.js +183 -183
  125. package/examples/jsm/loaders/GCodeLoader.js +261 -261
  126. package/examples/jsm/loaders/GLTFLoader.js +4666 -4579
  127. package/examples/jsm/loaders/GLTFLoaderAnimationPointer.js +719 -683
  128. package/examples/jsm/loaders/HDRCubeTextureLoader.js +115 -115
  129. package/examples/jsm/loaders/IESLoader.js +337 -337
  130. package/examples/jsm/loaders/KMZLoader.js +130 -130
  131. package/examples/jsm/loaders/KTX2Loader.js +932 -868
  132. package/examples/jsm/loaders/KTXLoader.js +176 -176
  133. package/examples/jsm/loaders/LDrawLoader.js +2470 -2464
  134. package/examples/jsm/loaders/LUT3dlLoader.js +183 -151
  135. package/examples/jsm/loaders/LUTCubeLoader.js +167 -153
  136. package/examples/jsm/loaders/LUTImageLoader.js +163 -0
  137. package/examples/jsm/loaders/LWOLoader.js +1052 -1052
  138. package/examples/jsm/loaders/LogLuvLoader.js +606 -606
  139. package/examples/jsm/loaders/LottieLoader.js +77 -77
  140. package/examples/jsm/loaders/MD2Loader.js +399 -399
  141. package/examples/jsm/loaders/MDDLoader.js +102 -102
  142. package/examples/jsm/loaders/MMDLoader.js +2276 -2273
  143. package/examples/jsm/loaders/MTLLoader.js +567 -567
  144. package/examples/jsm/loaders/MaterialXLoader.js +852 -734
  145. package/examples/jsm/loaders/NRRDLoader.js +686 -699
  146. package/examples/jsm/loaders/OBJLoader.js +905 -905
  147. package/examples/jsm/loaders/PCDLoader.js +467 -467
  148. package/examples/jsm/loaders/PDBLoader.js +232 -232
  149. package/examples/jsm/loaders/PLYLoader.js +771 -771
  150. package/examples/jsm/loaders/PVRLoader.js +251 -251
  151. package/examples/jsm/loaders/RGBELoader.js +450 -468
  152. package/examples/jsm/loaders/RGBMLoader.js +1065 -1065
  153. package/examples/jsm/loaders/STLLoader.js +410 -403
  154. package/examples/jsm/loaders/SVGLoader.js +3173 -3172
  155. package/examples/jsm/loaders/TDSLoader.js +1124 -1124
  156. package/examples/jsm/loaders/TGALoader.js +517 -517
  157. package/examples/jsm/loaders/TIFFLoader.js +36 -36
  158. package/examples/jsm/loaders/TTFLoader.js +214 -214
  159. package/examples/jsm/loaders/TiltLoader.js +520 -520
  160. package/examples/jsm/loaders/USDZLoader.js +822 -633
  161. package/examples/jsm/loaders/VOXLoader.js +311 -311
  162. package/examples/jsm/loaders/VRMLLoader.js +3533 -3533
  163. package/examples/jsm/loaders/VTKLoader.js +1163 -1163
  164. package/examples/jsm/loaders/XYZLoader.js +106 -106
  165. package/examples/jsm/loaders/lwo/IFFParser.js +1214 -1218
  166. package/examples/jsm/loaders/lwo/LWO2Parser.js +414 -414
  167. package/examples/jsm/loaders/lwo/LWO3Parser.js +373 -373
  168. package/examples/jsm/materials/MeshGouraudMaterial.js +426 -420
  169. package/examples/jsm/materials/MeshPostProcessingMaterial.js +144 -0
  170. package/examples/jsm/math/Capsule.js +82 -137
  171. package/examples/jsm/math/ColorConverter.js +36 -36
  172. package/examples/jsm/math/ConvexHull.js +1271 -1271
  173. package/examples/jsm/math/ImprovedNoise.js +71 -71
  174. package/examples/jsm/math/Lut.js +204 -204
  175. package/examples/jsm/math/MeshSurfaceSampler.js +250 -250
  176. package/examples/jsm/math/OBB.js +423 -423
  177. package/examples/jsm/math/Octree.js +540 -462
  178. package/examples/jsm/math/SimplexNoise.js +444 -444
  179. package/examples/jsm/misc/ConvexObjectBreaker.js +519 -519
  180. package/examples/jsm/misc/GPUComputationRenderer.js +446 -455
  181. package/examples/jsm/misc/Gyroscope.js +66 -66
  182. package/examples/jsm/misc/MD2Character.js +276 -276
  183. package/examples/jsm/misc/MD2CharacterComplex.js +576 -576
  184. package/examples/jsm/misc/MorphAnimMesh.js +75 -75
  185. package/examples/jsm/misc/MorphBlendMesh.js +322 -322
  186. package/examples/jsm/misc/ProgressiveLightMap.js +323 -323
  187. package/examples/jsm/misc/RollerCoaster.js +566 -566
  188. package/examples/jsm/misc/Timer.js +119 -0
  189. package/examples/jsm/misc/TubePainter.js +202 -205
  190. package/examples/jsm/misc/Volume.js +473 -475
  191. package/examples/jsm/misc/VolumeSlice.js +229 -229
  192. package/examples/jsm/modifiers/CurveModifier.js +344 -326
  193. package/examples/jsm/modifiers/EdgeSplitModifier.js +279 -279
  194. package/examples/jsm/modifiers/SimplifyModifier.js +617 -525
  195. package/examples/jsm/modifiers/TessellateModifier.js +307 -307
  196. package/examples/jsm/nodes/Nodes.js +189 -172
  197. package/examples/jsm/nodes/accessors/BitangentNode.js +89 -89
  198. package/examples/jsm/nodes/accessors/BufferAttributeNode.js +127 -99
  199. package/examples/jsm/nodes/accessors/BufferNode.js +30 -30
  200. package/examples/jsm/nodes/accessors/CameraNode.js +120 -98
  201. package/examples/jsm/nodes/accessors/CubeTextureNode.js +61 -101
  202. package/examples/jsm/nodes/accessors/InstanceNode.js +71 -71
  203. package/examples/jsm/nodes/accessors/InstancedPointsMaterialNode.js +21 -0
  204. package/examples/jsm/nodes/accessors/MaterialNode.js +314 -277
  205. package/examples/jsm/nodes/accessors/MaterialReferenceNode.js +51 -39
  206. package/examples/jsm/nodes/accessors/ModelNode.js +33 -34
  207. package/examples/jsm/nodes/accessors/ModelViewProjectionNode.js +39 -29
  208. package/examples/jsm/nodes/accessors/MorphNode.js +245 -70
  209. package/examples/jsm/nodes/accessors/NormalNode.js +96 -96
  210. package/examples/jsm/nodes/accessors/Object3DNode.js +150 -150
  211. package/examples/jsm/nodes/accessors/PointUVNode.js +26 -26
  212. package/examples/jsm/nodes/accessors/PositionNode.js +104 -104
  213. package/examples/jsm/nodes/accessors/ReferenceNode.js +102 -72
  214. package/examples/jsm/nodes/accessors/ReflectVectorNode.js +35 -35
  215. package/examples/jsm/nodes/accessors/SceneNode.js +52 -46
  216. package/examples/jsm/nodes/accessors/SkinningNode.js +103 -93
  217. package/examples/jsm/nodes/accessors/StorageBufferNode.js +54 -27
  218. package/examples/jsm/nodes/accessors/TangentNode.js +103 -103
  219. package/examples/jsm/nodes/accessors/TextureBicubicNode.js +94 -94
  220. package/examples/jsm/nodes/accessors/TextureNode.js +367 -230
  221. package/examples/jsm/nodes/accessors/TextureSizeNode.js +35 -35
  222. package/examples/jsm/nodes/accessors/TextureStoreNode.js +82 -0
  223. package/examples/jsm/nodes/accessors/UVNode.js +47 -47
  224. package/examples/jsm/nodes/accessors/UserDataNode.js +29 -29
  225. package/examples/jsm/nodes/accessors/VertexColorNode.js +70 -0
  226. package/examples/jsm/nodes/code/CodeNode.js +78 -78
  227. package/examples/jsm/nodes/code/ExpressionNode.js +37 -37
  228. package/examples/jsm/nodes/code/FunctionCallNode.js +96 -96
  229. package/examples/jsm/nodes/code/FunctionNode.js +138 -127
  230. package/examples/jsm/nodes/code/ScriptableNode.js +488 -488
  231. package/examples/jsm/nodes/code/ScriptableValueNode.js +167 -167
  232. package/examples/jsm/nodes/core/ArrayUniformNode.js +26 -26
  233. package/examples/jsm/nodes/core/AssignNode.js +72 -0
  234. package/examples/jsm/nodes/core/AttributeNode.js +108 -102
  235. package/examples/jsm/nodes/core/BypassNode.js +45 -45
  236. package/examples/jsm/nodes/core/CacheNode.js +49 -46
  237. package/examples/jsm/nodes/core/ConstNode.js +32 -32
  238. package/examples/jsm/nodes/core/ContextNode.js +61 -61
  239. package/examples/jsm/nodes/core/IndexNode.js +66 -66
  240. package/examples/jsm/nodes/core/InputNode.js +83 -83
  241. package/examples/jsm/nodes/core/LightingModel.js +17 -17
  242. package/examples/jsm/nodes/core/Node.js +483 -445
  243. package/examples/jsm/nodes/core/NodeAttribute.js +15 -15
  244. package/examples/jsm/nodes/core/NodeBuilder.js +1267 -1016
  245. package/examples/jsm/nodes/core/NodeCache.js +26 -26
  246. package/examples/jsm/nodes/core/NodeCode.js +15 -15
  247. package/examples/jsm/nodes/core/NodeFrame.js +135 -110
  248. package/examples/jsm/nodes/core/NodeFunction.js +22 -22
  249. package/examples/jsm/nodes/core/NodeFunctionInput.js +17 -17
  250. package/examples/jsm/nodes/core/NodeKeywords.js +80 -80
  251. package/examples/jsm/nodes/core/NodeParser.js +11 -11
  252. package/examples/jsm/nodes/core/NodeUniform.js +40 -28
  253. package/examples/jsm/nodes/core/NodeUtils.js +210 -212
  254. package/examples/jsm/nodes/core/NodeVar.js +14 -14
  255. package/examples/jsm/nodes/core/NodeVarying.js +17 -17
  256. package/examples/jsm/nodes/core/OutputStructNode.js +62 -0
  257. package/examples/jsm/nodes/core/ParameterNode.js +33 -0
  258. package/examples/jsm/nodes/core/PropertyNode.js +72 -57
  259. package/examples/jsm/nodes/core/StackNode.js +89 -99
  260. package/examples/jsm/nodes/core/StructTypeNode.js +24 -0
  261. package/examples/jsm/nodes/core/TempNode.js +58 -58
  262. package/examples/jsm/nodes/core/UniformGroup.js +13 -0
  263. package/examples/jsm/nodes/core/UniformGroupNode.js +36 -0
  264. package/examples/jsm/nodes/core/UniformNode.js +80 -61
  265. package/examples/jsm/nodes/core/VarNode.js +60 -87
  266. package/examples/jsm/nodes/core/VaryingNode.js +65 -69
  267. package/examples/jsm/nodes/core/constants.js +27 -27
  268. package/examples/jsm/nodes/display/AfterImageNode.js +134 -0
  269. package/examples/jsm/nodes/display/BlendModeNode.js +99 -99
  270. package/examples/jsm/nodes/display/BumpMapNode.js +99 -0
  271. package/examples/jsm/nodes/display/ColorAdjustmentNode.js +96 -100
  272. package/examples/jsm/nodes/display/ColorSpaceNode.js +108 -108
  273. package/examples/jsm/nodes/display/FrontFacingNode.js +27 -27
  274. package/examples/jsm/nodes/display/GaussianBlurNode.js +177 -0
  275. package/examples/jsm/nodes/display/NormalMapNode.js +108 -106
  276. package/examples/jsm/nodes/display/PassNode.js +182 -0
  277. package/examples/jsm/nodes/display/PosterizeNode.js +32 -32
  278. package/examples/jsm/nodes/display/ToneMappingNode.js +184 -141
  279. package/examples/jsm/nodes/display/ViewportDepthNode.js +97 -69
  280. package/examples/jsm/nodes/display/ViewportDepthTextureNode.js +31 -34
  281. package/examples/jsm/nodes/display/ViewportNode.js +134 -115
  282. package/examples/jsm/nodes/display/ViewportSharedTextureNode.js +31 -31
  283. package/examples/jsm/nodes/display/ViewportTextureNode.js +75 -75
  284. package/examples/jsm/nodes/fog/FogExp2Node.js +35 -35
  285. package/examples/jsm/nodes/fog/FogNode.js +38 -37
  286. package/examples/jsm/nodes/fog/FogRangeNode.js +34 -34
  287. package/examples/jsm/nodes/functions/BSDF/BRDF_GGX.js +40 -32
  288. package/examples/jsm/nodes/functions/BSDF/BRDF_Lambert.js +9 -9
  289. package/examples/jsm/nodes/functions/BSDF/BRDF_Sheen.js +57 -43
  290. package/examples/jsm/nodes/functions/BSDF/DFGApprox.js +30 -29
  291. package/examples/jsm/nodes/functions/BSDF/D_GGX.js +23 -18
  292. package/examples/jsm/nodes/functions/BSDF/EnvironmentBRDF.js +13 -13
  293. package/examples/jsm/nodes/functions/BSDF/F_Schlick.js +16 -16
  294. package/examples/jsm/nodes/functions/BSDF/Schlick_to_F0.js +21 -0
  295. package/examples/jsm/nodes/functions/BSDF/V_GGX_SmithCorrelated.js +28 -20
  296. package/examples/jsm/nodes/functions/PhongLightingModel.js +67 -28
  297. package/examples/jsm/nodes/functions/PhysicalLightingModel.js +393 -204
  298. package/examples/jsm/nodes/functions/material/getGeometryRoughness.js +13 -13
  299. package/examples/jsm/nodes/functions/material/getRoughness.js +18 -18
  300. package/examples/jsm/nodes/geometry/RangeNode.js +104 -104
  301. package/examples/jsm/nodes/gpgpu/ComputeNode.js +85 -72
  302. package/examples/jsm/nodes/lighting/AONode.js +27 -27
  303. package/examples/jsm/nodes/lighting/AmbientLightNode.js +27 -27
  304. package/examples/jsm/nodes/lighting/AnalyticLightNode.js +238 -146
  305. package/examples/jsm/nodes/lighting/DirectionalLightNode.js +40 -43
  306. package/examples/jsm/nodes/lighting/EnvironmentNode.js +181 -181
  307. package/examples/jsm/nodes/lighting/HemisphereLightNode.js +55 -55
  308. package/examples/jsm/nodes/lighting/IESSpotLightNode.js +39 -39
  309. package/examples/jsm/nodes/lighting/LightNode.js +57 -57
  310. package/examples/jsm/nodes/lighting/LightUtils.js +17 -17
  311. package/examples/jsm/nodes/lighting/LightingContextNode.js +66 -99
  312. package/examples/jsm/nodes/lighting/LightingNode.js +21 -21
  313. package/examples/jsm/nodes/lighting/LightsNode.js +188 -128
  314. package/examples/jsm/nodes/lighting/PointLightNode.js +68 -71
  315. package/examples/jsm/nodes/lighting/SpotLightNode.js +89 -92
  316. package/examples/jsm/nodes/loaders/NodeLoader.js +108 -108
  317. package/examples/jsm/nodes/loaders/NodeMaterialLoader.js +59 -59
  318. package/examples/jsm/nodes/loaders/NodeObjectLoader.js +70 -70
  319. package/examples/jsm/nodes/materials/InstancedPointsNodeMaterial.js +162 -0
  320. package/examples/jsm/nodes/materials/Line2NodeMaterial.js +436 -0
  321. package/examples/jsm/nodes/materials/LineBasicNodeMaterial.js +28 -28
  322. package/examples/jsm/nodes/materials/LineDashedNodeMaterial.js +54 -0
  323. package/examples/jsm/nodes/materials/Materials.js +16 -11
  324. package/examples/jsm/nodes/materials/MeshBasicNodeMaterial.js +28 -27
  325. package/examples/jsm/nodes/materials/MeshLambertNodeMaterial.js +34 -0
  326. package/examples/jsm/nodes/materials/MeshNormalNodeMaterial.js +40 -38
  327. package/examples/jsm/nodes/materials/MeshPhongNodeMaterial.js +65 -65
  328. package/examples/jsm/nodes/materials/MeshPhysicalNodeMaterial.js +155 -111
  329. package/examples/jsm/nodes/materials/MeshSSSNodeMaterial.js +84 -0
  330. package/examples/jsm/nodes/materials/MeshStandardNodeMaterial.js +80 -80
  331. package/examples/jsm/nodes/materials/NodeMaterial.js +568 -510
  332. package/examples/jsm/nodes/materials/PointsNodeMaterial.js +39 -49
  333. package/examples/jsm/nodes/materials/SpriteNodeMaterial.js +96 -103
  334. package/examples/jsm/nodes/materialx/DISCLAIMER.md +199 -199
  335. package/examples/jsm/nodes/materialx/MaterialXNodes.js +68 -68
  336. package/examples/jsm/nodes/materialx/lib/mx_hsv.js +130 -56
  337. package/examples/jsm/nodes/materialx/lib/mx_noise.js +1430 -618
  338. package/examples/jsm/nodes/materialx/lib/mx_transform_color.js +29 -19
  339. package/examples/jsm/nodes/math/CondNode.js +86 -86
  340. package/examples/jsm/nodes/math/HashNode.js +34 -0
  341. package/examples/jsm/nodes/math/MathNode.js +382 -359
  342. package/examples/jsm/nodes/math/OperatorNode.js +266 -269
  343. package/examples/jsm/nodes/math/TriNoise3D.js +71 -0
  344. package/examples/jsm/nodes/parsers/GLSLNodeFunction.js +152 -152
  345. package/examples/jsm/nodes/parsers/GLSLNodeParser.js +14 -14
  346. package/examples/jsm/nodes/procedural/CheckerNode.js +42 -42
  347. package/examples/jsm/nodes/shadernode/ShaderNode.js +625 -420
  348. package/examples/jsm/nodes/utils/ArrayElementNode.js +41 -33
  349. package/examples/jsm/nodes/utils/ConvertNode.js +65 -65
  350. package/examples/jsm/nodes/utils/DiscardNode.js +27 -26
  351. package/examples/jsm/nodes/utils/EquirectUVNode.js +33 -33
  352. package/examples/jsm/nodes/utils/FunctionOverloadingNode.js +95 -0
  353. package/examples/jsm/nodes/utils/JoinNode.js +61 -51
  354. package/examples/jsm/nodes/utils/LoopNode.js +198 -186
  355. package/examples/jsm/nodes/utils/MatcapUVNode.js +30 -30
  356. package/examples/jsm/nodes/utils/MaxMipLevelNode.js +46 -46
  357. package/examples/jsm/nodes/utils/OscNode.js +81 -81
  358. package/examples/jsm/nodes/utils/PackingNode.js +55 -55
  359. package/examples/jsm/nodes/utils/RemapNode.js +42 -42
  360. package/examples/jsm/nodes/utils/RotateNode.js +43 -0
  361. package/examples/jsm/nodes/utils/RotateUVNode.js +43 -43
  362. package/examples/jsm/nodes/utils/SetNode.js +62 -0
  363. package/examples/jsm/nodes/utils/SpecularMIPLevelNode.js +37 -37
  364. package/examples/jsm/nodes/utils/SplitNode.js +112 -104
  365. package/examples/jsm/nodes/utils/SpriteSheetUVNode.js +41 -41
  366. package/examples/jsm/nodes/utils/TimerNode.js +94 -94
  367. package/examples/jsm/nodes/utils/TriplanarTexturesNode.js +62 -62
  368. package/examples/jsm/objects/GroundedSkybox.js +50 -0
  369. package/examples/jsm/objects/InstancedPoints.js +21 -0
  370. package/examples/jsm/objects/Lensflare.js +397 -377
  371. package/examples/jsm/objects/MarchingCubes.js +1176 -1176
  372. package/examples/jsm/objects/QuadMesh.js +66 -0
  373. package/examples/jsm/objects/Reflector.js +264 -272
  374. package/examples/jsm/objects/ReflectorForSSRPass.js +352 -349
  375. package/examples/jsm/objects/Refractor.js +327 -332
  376. package/examples/jsm/objects/ShadowMesh.js +80 -80
  377. package/examples/jsm/objects/Sky.js +219 -219
  378. package/examples/jsm/objects/Water.js +333 -330
  379. package/examples/jsm/objects/Water2.js +361 -358
  380. package/examples/jsm/offscreen/jank.js +45 -45
  381. package/examples/jsm/offscreen/offscreen.js +8 -8
  382. package/examples/jsm/offscreen/scene.js +86 -87
  383. package/examples/jsm/physics/AmmoPhysics.js +306 -285
  384. package/examples/jsm/physics/RapierPhysics.js +220 -199
  385. package/examples/jsm/postprocessing/AfterimagePass.js +104 -104
  386. package/examples/jsm/postprocessing/BloomPass.js +172 -172
  387. package/examples/jsm/postprocessing/BokehPass.js +141 -140
  388. package/examples/jsm/postprocessing/ClearPass.js +46 -46
  389. package/examples/jsm/postprocessing/CubeTexturePass.js +85 -85
  390. package/examples/jsm/postprocessing/DotScreenPass.js +65 -65
  391. package/examples/jsm/postprocessing/EffectComposer.js +231 -231
  392. package/examples/jsm/postprocessing/FilmPass.js +64 -66
  393. package/examples/jsm/postprocessing/GTAOPass.js +582 -0
  394. package/examples/jsm/postprocessing/GlitchPass.js +128 -128
  395. package/examples/jsm/postprocessing/HalftonePass.js +79 -79
  396. package/examples/jsm/postprocessing/LUTPass.js +174 -173
  397. package/examples/jsm/postprocessing/MaskPass.js +104 -101
  398. package/examples/jsm/postprocessing/OutlinePass.js +654 -654
  399. package/examples/jsm/postprocessing/OutputPass.js +95 -72
  400. package/examples/jsm/postprocessing/Pass.js +95 -84
  401. package/examples/jsm/postprocessing/RenderPass.js +99 -81
  402. package/examples/jsm/postprocessing/RenderPixelatedPass.js +235 -235
  403. package/examples/jsm/postprocessing/SAOPass.js +335 -411
  404. package/examples/jsm/postprocessing/SMAAPass.js +199 -201
  405. package/examples/jsm/postprocessing/SSAARenderPass.js +228 -228
  406. package/examples/jsm/postprocessing/SSAOPass.js +420 -440
  407. package/examples/jsm/postprocessing/SSRPass.js +641 -641
  408. package/examples/jsm/postprocessing/SavePass.js +79 -79
  409. package/examples/jsm/postprocessing/ShaderPass.js +77 -77
  410. package/examples/jsm/postprocessing/TAARenderPass.js +188 -189
  411. package/examples/jsm/postprocessing/TexturePass.js +67 -67
  412. package/examples/jsm/postprocessing/UnrealBloomPass.js +415 -411
  413. package/examples/jsm/renderers/CSS2DRenderer.js +215 -215
  414. package/examples/jsm/renderers/CSS3DRenderer.js +329 -335
  415. package/examples/jsm/renderers/Projector.js +918 -918
  416. package/examples/jsm/renderers/SVGRenderer.js +556 -553
  417. package/examples/jsm/renderers/common/Animation.js +47 -58
  418. package/examples/jsm/renderers/common/Attributes.js +75 -75
  419. package/examples/jsm/renderers/common/Backend.js +193 -162
  420. package/examples/jsm/renderers/common/Background.js +134 -134
  421. package/examples/jsm/renderers/common/Binding.js +25 -11
  422. package/examples/jsm/renderers/common/Bindings.js +173 -169
  423. package/examples/jsm/renderers/common/Buffer.js +38 -38
  424. package/examples/jsm/renderers/common/BufferUtils.js +33 -33
  425. package/examples/jsm/renderers/common/ChainMap.js +89 -89
  426. package/examples/jsm/renderers/common/Color4.js +37 -0
  427. package/examples/jsm/renderers/common/ComputePipeline.js +17 -17
  428. package/examples/jsm/renderers/common/Constants.js +14 -14
  429. package/examples/jsm/renderers/common/CubeRenderTarget.js +65 -65
  430. package/examples/jsm/renderers/common/DataMap.js +54 -54
  431. package/examples/jsm/renderers/common/Geometries.js +215 -215
  432. package/examples/jsm/renderers/common/Info.js +107 -73
  433. package/examples/jsm/renderers/common/Pipeline.js +13 -13
  434. package/examples/jsm/renderers/common/Pipelines.js +322 -321
  435. package/examples/jsm/renderers/common/PostProcessing.js +25 -0
  436. package/examples/jsm/renderers/common/ProgrammableStage.js +20 -18
  437. package/examples/jsm/renderers/common/RenderContext.js +41 -37
  438. package/examples/jsm/renderers/common/RenderContexts.js +74 -38
  439. package/examples/jsm/renderers/common/RenderList.js +186 -178
  440. package/examples/jsm/renderers/common/RenderLists.js +38 -38
  441. package/examples/jsm/renderers/common/RenderObject.js +178 -113
  442. package/examples/jsm/renderers/common/RenderObjects.js +91 -92
  443. package/examples/jsm/renderers/common/RenderPipeline.js +16 -16
  444. package/examples/jsm/renderers/common/Renderer.js +1062 -864
  445. package/examples/jsm/renderers/common/SampledTexture.js +83 -80
  446. package/examples/jsm/renderers/common/Sampler.js +18 -18
  447. package/examples/jsm/renderers/common/StorageBuffer.js +17 -17
  448. package/examples/jsm/renderers/common/StorageBufferAttribute.js +21 -0
  449. package/examples/jsm/renderers/common/StorageTexture.js +20 -0
  450. package/examples/jsm/renderers/common/Textures.js +354 -206
  451. package/examples/jsm/renderers/common/Uniform.js +140 -140
  452. package/examples/jsm/renderers/common/UniformBuffer.js +15 -15
  453. package/examples/jsm/renderers/common/UniformsGroup.js +299 -299
  454. package/examples/jsm/renderers/common/nodes/NodeBuilderState.js +44 -0
  455. package/examples/jsm/renderers/common/nodes/NodeSampledTexture.js +49 -39
  456. package/examples/jsm/renderers/common/nodes/NodeSampler.js +15 -21
  457. package/examples/jsm/renderers/common/nodes/NodeUniform.js +135 -135
  458. package/examples/jsm/renderers/common/nodes/NodeUniformsGroup.js +44 -0
  459. package/examples/jsm/renderers/common/nodes/Nodes.js +495 -319
  460. package/examples/jsm/renderers/webgl/WebGLBackend.js +1290 -0
  461. package/examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js +679 -340
  462. package/examples/jsm/renderers/webgl/utils/WebGLAttributeUtils.js +252 -0
  463. package/examples/jsm/renderers/webgl/utils/WebGLCapabilities.js +36 -0
  464. package/examples/jsm/renderers/webgl/utils/WebGLConstants.js +11 -0
  465. package/examples/jsm/renderers/webgl/utils/WebGLExtensions.js +36 -0
  466. package/examples/jsm/renderers/webgl/utils/WebGLState.js +738 -0
  467. package/examples/jsm/renderers/webgl/utils/WebGLTextureUtils.js +647 -0
  468. package/examples/jsm/renderers/webgl/utils/WebGLUtils.js +284 -0
  469. package/examples/jsm/renderers/webgl-legacy/nodes/GLSL1NodeBuilder.js +320 -0
  470. package/examples/jsm/renderers/{webgl → webgl-legacy}/nodes/SlotNode.js +26 -26
  471. package/examples/jsm/renderers/{webgl → webgl-legacy}/nodes/WebGLNodeBuilder.js +794 -764
  472. package/examples/jsm/renderers/{webgl → webgl-legacy}/nodes/WebGLNodes.js +51 -49
  473. package/examples/jsm/renderers/webgpu/WebGPUBackend.js +1321 -847
  474. package/examples/jsm/renderers/webgpu/WebGPURenderer.js +53 -32
  475. package/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js +1098 -878
  476. package/examples/jsm/renderers/webgpu/nodes/WGSLNodeFunction.js +104 -104
  477. package/examples/jsm/renderers/webgpu/nodes/WGSLNodeParser.js +14 -14
  478. package/examples/jsm/renderers/webgpu/utils/WebGPUAttributeUtils.js +287 -255
  479. package/examples/jsm/renderers/webgpu/utils/WebGPUBindingUtils.js +244 -145
  480. package/examples/jsm/renderers/webgpu/utils/WebGPUConstants.js +324 -322
  481. package/examples/jsm/renderers/webgpu/utils/WebGPUPipelineUtils.js +570 -580
  482. package/examples/jsm/renderers/webgpu/utils/WebGPUTexturePassUtils.js +285 -0
  483. package/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js +1040 -937
  484. package/examples/jsm/renderers/webgpu/utils/WebGPUUtils.js +93 -92
  485. package/examples/jsm/shaders/ACESFilmicToneMappingShader.js +89 -87
  486. package/examples/jsm/shaders/AfterimageShader.js +58 -56
  487. package/examples/jsm/shaders/BasicShader.js +29 -27
  488. package/examples/jsm/shaders/BleachBypassShader.js +62 -62
  489. package/examples/jsm/shaders/BlendShader.js +49 -47
  490. package/examples/jsm/shaders/BokehShader.js +145 -143
  491. package/examples/jsm/shaders/BokehShader2.js +397 -393
  492. package/examples/jsm/shaders/BrightnessContrastShader.js +56 -54
  493. package/examples/jsm/shaders/ColorCorrectionShader.js +52 -50
  494. package/examples/jsm/shaders/ColorifyShader.js +51 -51
  495. package/examples/jsm/shaders/ConvolutionShader.js +103 -103
  496. package/examples/jsm/shaders/CopyShader.js +45 -45
  497. package/examples/jsm/shaders/DOFMipMapShader.js +56 -54
  498. package/examples/jsm/shaders/DepthLimitedBlurShader.js +171 -166
  499. package/examples/jsm/shaders/DigitalGlitch.js +101 -101
  500. package/examples/jsm/shaders/DotScreenShader.js +70 -70
  501. package/examples/jsm/shaders/ExposureShader.js +44 -44
  502. package/examples/jsm/shaders/FXAAShader.js +288 -286
  503. package/examples/jsm/shaders/FilmShader.js +59 -102
  504. package/examples/jsm/shaders/FocusShader.js +89 -87
  505. package/examples/jsm/shaders/FreiChenShader.js +96 -94
  506. package/examples/jsm/shaders/GTAOShader.js +424 -0
  507. package/examples/jsm/shaders/GammaCorrectionShader.js +43 -43
  508. package/examples/jsm/shaders/GodRaysShader.js +321 -313
  509. package/examples/jsm/shaders/HalftoneShader.js +312 -310
  510. package/examples/jsm/shaders/HorizontalBlurShader.js +59 -59
  511. package/examples/jsm/shaders/HorizontalTiltShiftShader.js +63 -61
  512. package/examples/jsm/shaders/HueSaturationShader.js +67 -65
  513. package/examples/jsm/shaders/KaleidoShader.js +58 -56
  514. package/examples/jsm/shaders/LuminosityHighPassShader.js +66 -64
  515. package/examples/jsm/shaders/LuminosityShader.js +48 -46
  516. package/examples/jsm/shaders/MMDToonShader.js +134 -132
  517. package/examples/jsm/shaders/MirrorShader.js +56 -54
  518. package/examples/jsm/shaders/NormalMapShader.js +55 -53
  519. package/examples/jsm/shaders/OutputShader.js +81 -61
  520. package/examples/jsm/shaders/PoissonDenoiseShader.js +226 -0
  521. package/examples/jsm/shaders/RGBShiftShader.js +54 -54
  522. package/examples/jsm/shaders/SAOShader.js +179 -188
  523. package/examples/jsm/shaders/SMAAShader.js +466 -460
  524. package/examples/jsm/shaders/SSAOShader.js +300 -288
  525. package/examples/jsm/shaders/SSRShader.js +370 -364
  526. package/examples/jsm/shaders/SepiaShader.js +52 -52
  527. package/examples/jsm/shaders/SobelOperatorShader.js +92 -90
  528. package/examples/jsm/shaders/SubsurfaceScatteringShader.js +90 -88
  529. package/examples/jsm/shaders/TechnicolorShader.js +45 -43
  530. package/examples/jsm/shaders/ToonShader.js +326 -326
  531. package/examples/jsm/shaders/TriangleBlurShader.js +74 -72
  532. package/examples/jsm/shaders/UnpackDepthRGBAShader.js +47 -45
  533. package/examples/jsm/shaders/VelocityShader.js +130 -128
  534. package/examples/jsm/shaders/VerticalBlurShader.js +59 -59
  535. package/examples/jsm/shaders/VerticalTiltShiftShader.js +63 -61
  536. package/examples/jsm/shaders/VignetteShader.js +51 -51
  537. package/examples/jsm/shaders/VolumeShader.js +289 -289
  538. package/examples/jsm/shaders/WaterRefractionShader.js +95 -93
  539. package/examples/jsm/textures/FlakesTexture.js +40 -40
  540. package/examples/jsm/transpiler/AST.js +270 -0
  541. package/examples/jsm/transpiler/GLSLDecoder.js +941 -0
  542. package/examples/jsm/transpiler/ShaderToyDecoder.js +49 -0
  543. package/examples/jsm/transpiler/TSLEncoder.js +715 -0
  544. package/examples/jsm/transpiler/Transpiler.js +18 -0
  545. package/examples/jsm/utils/BufferGeometryUtils.js +1371 -1364
  546. package/examples/jsm/utils/CameraUtils.js +73 -73
  547. package/examples/jsm/utils/GPUStatsPanel.js +128 -128
  548. package/examples/jsm/utils/GeometryCompressionUtils.js +639 -639
  549. package/examples/jsm/utils/GeometryUtils.js +221 -221
  550. package/examples/jsm/utils/LDrawUtils.js +202 -202
  551. package/examples/jsm/utils/PackedPhongMaterial.js +178 -178
  552. package/examples/jsm/utils/SceneUtils.js +254 -254
  553. package/examples/jsm/utils/ShadowMapViewer.js +210 -210
  554. package/examples/jsm/utils/SkeletonUtils.js +413 -413
  555. package/examples/jsm/utils/SortUtils.js +160 -0
  556. package/examples/jsm/utils/TextureUtils.js +98 -86
  557. package/examples/jsm/utils/UVsDebug.js +165 -165
  558. package/examples/jsm/utils/WorkerPool.js +102 -102
  559. package/examples/jsm/webxr/ARButton.js +232 -208
  560. package/examples/jsm/webxr/OculusHandModel.js +109 -109
  561. package/examples/jsm/webxr/OculusHandPointerModel.js +416 -415
  562. package/examples/jsm/webxr/Text2D.js +38 -38
  563. package/examples/jsm/webxr/VRButton.js +225 -200
  564. package/examples/jsm/webxr/XRButton.js +224 -198
  565. package/examples/jsm/webxr/XRControllerModelFactory.js +315 -310
  566. package/examples/jsm/webxr/XREstimatedLight.js +223 -223
  567. package/examples/jsm/webxr/XRHandMeshModel.js +116 -113
  568. package/examples/jsm/webxr/XRHandModelFactory.js +105 -105
  569. package/examples/jsm/webxr/XRHandPrimitiveModel.js +105 -104
  570. package/examples/jsm/webxr/XRPlanes.js +100 -100
  571. package/package.json +129 -126
  572. package/src/Three.Legacy.js +1 -1
  573. package/src/Three.js +184 -182
  574. package/src/animation/AnimationAction.js +700 -700
  575. package/src/animation/AnimationClip.js +473 -473
  576. package/src/animation/AnimationMixer.js +770 -770
  577. package/src/animation/AnimationObjectGroup.js +387 -387
  578. package/src/animation/AnimationUtils.js +356 -373
  579. package/src/animation/KeyframeTrack.js +462 -462
  580. package/src/animation/PropertyBinding.js +719 -719
  581. package/src/animation/PropertyMixer.js +318 -318
  582. package/src/animation/tracks/BooleanKeyframeTrack.js +19 -19
  583. package/src/animation/tracks/ColorKeyframeTrack.js +15 -15
  584. package/src/animation/tracks/NumberKeyframeTrack.js +12 -12
  585. package/src/animation/tracks/QuaternionKeyframeTrack.js +23 -23
  586. package/src/animation/tracks/StringKeyframeTrack.js +15 -15
  587. package/src/animation/tracks/VectorKeyframeTrack.js +12 -12
  588. package/src/audio/Audio.js +400 -396
  589. package/src/audio/AudioAnalyser.js +40 -40
  590. package/src/audio/AudioContext.js +25 -25
  591. package/src/audio/AudioListener.js +140 -137
  592. package/src/audio/PositionalAudio.js +146 -146
  593. package/src/cameras/ArrayCamera.js +17 -17
  594. package/src/cameras/Camera.js +69 -73
  595. package/src/cameras/CubeCamera.js +173 -170
  596. package/src/cameras/OrthographicCamera.js +136 -136
  597. package/src/cameras/PerspectiveCamera.js +268 -233
  598. package/src/cameras/StereoCamera.js +100 -100
  599. package/src/constants.js +216 -201
  600. package/src/core/BufferAttribute.js +650 -610
  601. package/src/core/BufferGeometry.js +1079 -1079
  602. package/src/core/Clock.js +74 -74
  603. package/src/core/EventDispatcher.js +87 -87
  604. package/src/core/GLBufferAttribute.js +60 -60
  605. package/src/core/InstancedBufferAttribute.js +39 -39
  606. package/src/core/InstancedBufferGeometry.js +40 -40
  607. package/src/core/InstancedInterleavedBuffer.js +48 -48
  608. package/src/core/InterleavedBuffer.js +166 -145
  609. package/src/core/InterleavedBufferAttribute.js +351 -331
  610. package/src/core/Layers.js +60 -60
  611. package/src/core/Object3D.js +1008 -973
  612. package/src/core/Raycaster.js +110 -110
  613. package/src/core/RenderTarget.js +131 -0
  614. package/src/core/Uniform.js +17 -17
  615. package/src/core/UniformsGroup.js +98 -92
  616. package/src/extras/DataUtils.js +176 -176
  617. package/src/extras/Earcut.js +789 -789
  618. package/src/extras/ImageUtils.js +129 -129
  619. package/src/extras/PMREMGenerator.js +910 -903
  620. package/src/extras/ShapeUtils.js +92 -92
  621. package/src/extras/core/Curve.js +416 -416
  622. package/src/extras/core/CurvePath.js +255 -252
  623. package/src/extras/core/Interpolations.js +79 -79
  624. package/src/extras/core/Path.js +196 -196
  625. package/src/extras/core/Shape.js +102 -102
  626. package/src/extras/core/ShapePath.js +291 -291
  627. package/src/extras/curves/ArcCurve.js +17 -17
  628. package/src/extras/curves/CatmullRomCurve3.js +255 -255
  629. package/src/extras/curves/CubicBezierCurve.js +78 -78
  630. package/src/extras/curves/CubicBezierCurve3.js +79 -79
  631. package/src/extras/curves/Curves.js +10 -10
  632. package/src/extras/curves/EllipseCurve.js +156 -156
  633. package/src/extras/curves/LineCurve.js +92 -92
  634. package/src/extras/curves/LineCurve3.js +92 -88
  635. package/src/extras/curves/QuadraticBezierCurve.js +74 -74
  636. package/src/extras/curves/QuadraticBezierCurve3.js +75 -75
  637. package/src/extras/curves/SplineCurve.js +97 -97
  638. package/src/geometries/BoxGeometry.js +180 -180
  639. package/src/geometries/CapsuleGeometry.js +33 -33
  640. package/src/geometries/CircleGeometry.js +101 -101
  641. package/src/geometries/ConeGeometry.js +31 -31
  642. package/src/geometries/CylinderGeometry.js +286 -286
  643. package/src/geometries/DodecahedronGeometry.js +66 -66
  644. package/src/geometries/EdgesGeometry.js +152 -152
  645. package/src/geometries/ExtrudeGeometry.js +814 -814
  646. package/src/geometries/Geometries.js +21 -21
  647. package/src/geometries/IcosahedronGeometry.js +42 -42
  648. package/src/geometries/LatheGeometry.js +189 -189
  649. package/src/geometries/OctahedronGeometry.js +37 -37
  650. package/src/geometries/PlaneGeometry.js +98 -98
  651. package/src/geometries/PolyhedronGeometry.js +319 -319
  652. package/src/geometries/RingGeometry.js +128 -128
  653. package/src/geometries/ShapeGeometry.js +195 -195
  654. package/src/geometries/SphereGeometry.js +137 -137
  655. package/src/geometries/TetrahedronGeometry.js +34 -34
  656. package/src/geometries/TorusGeometry.js +120 -120
  657. package/src/geometries/TorusKnotGeometry.js +167 -167
  658. package/src/geometries/TubeGeometry.js +203 -203
  659. package/src/geometries/WireframeGeometry.js +147 -147
  660. package/src/helpers/ArrowHelper.js +114 -114
  661. package/src/helpers/AxesHelper.js +68 -68
  662. package/src/helpers/Box3Helper.js +55 -55
  663. package/src/helpers/BoxHelper.js +113 -113
  664. package/src/helpers/CameraHelper.js +269 -269
  665. package/src/helpers/DirectionalLightHelper.js +93 -93
  666. package/src/helpers/GridHelper.js +56 -56
  667. package/src/helpers/HemisphereLightHelper.js +88 -88
  668. package/src/helpers/PlaneHelper.js +63 -63
  669. package/src/helpers/PointLightHelper.js +92 -92
  670. package/src/helpers/PolarGridHelper.js +96 -96
  671. package/src/helpers/SkeletonHelper.js +128 -128
  672. package/src/helpers/SpotLightHelper.js +94 -94
  673. package/src/lights/AmbientLight.js +17 -17
  674. package/src/lights/DirectionalLight.js +43 -43
  675. package/src/lights/DirectionalLightShadow.js +16 -16
  676. package/src/lights/HemisphereLight.js +34 -34
  677. package/src/lights/Light.js +58 -58
  678. package/src/lights/LightProbe.js +47 -47
  679. package/src/lights/LightShadow.js +147 -147
  680. package/src/lights/PointLight.js +57 -57
  681. package/src/lights/PointLightShadow.js +96 -96
  682. package/src/lights/RectAreaLight.js +56 -56
  683. package/src/lights/SpotLight.js +71 -71
  684. package/src/lights/SpotLightShadow.js +50 -50
  685. package/src/loaders/AnimationLoader.js +66 -66
  686. package/src/loaders/AudioLoader.js +66 -66
  687. package/src/loaders/BufferGeometryLoader.js +217 -224
  688. package/src/loaders/Cache.js +42 -42
  689. package/src/loaders/CompressedTextureLoader.js +134 -134
  690. package/src/loaders/CubeTextureLoader.js +58 -58
  691. package/src/loaders/DataTextureLoader.js +135 -118
  692. package/src/loaders/FileLoader.js +284 -284
  693. package/src/loaders/ImageBitmapLoader.js +123 -99
  694. package/src/loaders/ImageLoader.js +91 -91
  695. package/src/loaders/Loader.js +72 -72
  696. package/src/loaders/LoaderUtils.js +75 -75
  697. package/src/loaders/LoadingManager.js +142 -142
  698. package/src/loaders/MaterialLoader.js +372 -364
  699. package/src/loaders/ObjectLoader.js +1148 -1093
  700. package/src/loaders/TextureLoader.js +41 -41
  701. package/src/materials/LineBasicMaterial.js +53 -49
  702. package/src/materials/LineDashedMaterial.js +35 -35
  703. package/src/materials/Material.js +522 -508
  704. package/src/materials/Materials.js +39 -39
  705. package/src/materials/MeshBasicMaterial.js +85 -81
  706. package/src/materials/MeshDepthMaterial.js +54 -54
  707. package/src/materials/MeshDistanceMaterial.js +43 -43
  708. package/src/materials/MeshLambertMaterial.js +120 -116
  709. package/src/materials/MeshMatcapMaterial.js +85 -81
  710. package/src/materials/MeshNormalMaterial.js +61 -61
  711. package/src/materials/MeshPhongMaterial.js +124 -120
  712. package/src/materials/MeshPhysicalMaterial.js +224 -224
  713. package/src/materials/MeshStandardMaterial.js +128 -124
  714. package/src/materials/MeshToonMaterial.js +106 -102
  715. package/src/materials/PointsMaterial.js +54 -50
  716. package/src/materials/RawShaderMaterial.js +17 -17
  717. package/src/materials/ShaderMaterial.js +190 -187
  718. package/src/materials/ShadowMaterial.js +37 -37
  719. package/src/materials/SpriteMaterial.js +54 -54
  720. package/src/math/Box2.js +204 -204
  721. package/src/math/Box3.js +534 -517
  722. package/src/math/Color.js +623 -627
  723. package/src/math/ColorManagement.js +139 -133
  724. package/src/math/Cylindrical.js +61 -61
  725. package/src/math/Euler.js +315 -315
  726. package/src/math/Frustum.js +186 -186
  727. package/src/math/Interpolant.js +241 -241
  728. package/src/math/Line3.js +115 -115
  729. package/src/math/MathUtils.js +363 -363
  730. package/src/math/Matrix3.js +388 -388
  731. package/src/math/Matrix4.js +915 -915
  732. package/src/math/Plane.js +205 -205
  733. package/src/math/Quaternion.js +685 -684
  734. package/src/math/Ray.js +493 -493
  735. package/src/math/Sphere.js +245 -243
  736. package/src/math/Spherical.js +86 -86
  737. package/src/math/SphericalHarmonics3.js +243 -243
  738. package/src/math/Triangle.js +311 -329
  739. package/src/math/Vector2.js +480 -480
  740. package/src/math/Vector3.js +724 -725
  741. package/src/math/Vector4.js +644 -644
  742. package/src/math/interpolants/CubicInterpolant.js +150 -150
  743. package/src/math/interpolants/DiscreteInterpolant.js +26 -26
  744. package/src/math/interpolants/LinearInterpolant.js +38 -38
  745. package/src/math/interpolants/QuaternionLinearInterpolant.js +39 -39
  746. package/src/objects/BatchedMesh.js +1019 -0
  747. package/src/objects/Bone.js +17 -17
  748. package/src/objects/Group.js +17 -17
  749. package/src/objects/InstancedMesh.js +214 -214
  750. package/src/objects/LOD.js +214 -214
  751. package/src/objects/Line.js +222 -222
  752. package/src/objects/LineLoop.js +17 -17
  753. package/src/objects/LineSegments.js +55 -55
  754. package/src/objects/Mesh.js +429 -429
  755. package/src/objects/Points.js +166 -166
  756. package/src/objects/Skeleton.js +277 -279
  757. package/src/objects/SkinnedMesh.js +257 -266
  758. package/src/objects/Sprite.js +181 -181
  759. package/src/renderers/WebGL1Renderer.js +7 -7
  760. package/src/renderers/WebGL3DRenderTarget.js +22 -22
  761. package/src/renderers/WebGLArrayRenderTarget.js +22 -22
  762. package/src/renderers/WebGLCubeRenderTarget.js +155 -155
  763. package/src/renderers/WebGLMultipleRenderTargets.js +82 -84
  764. package/src/renderers/WebGLRenderTarget.js +15 -122
  765. package/src/renderers/WebGLRenderer.js +2631 -2439
  766. package/src/renderers/shaders/ShaderChunk/alphahash_fragment.glsl.js +7 -7
  767. package/src/renderers/shaders/ShaderChunk/alphahash_pars_fragment.glsl.js +68 -68
  768. package/src/renderers/shaders/ShaderChunk/alphamap_fragment.glsl.js +7 -7
  769. package/src/renderers/shaders/ShaderChunk/alphamap_pars_fragment.glsl.js +7 -7
  770. package/src/renderers/shaders/ShaderChunk/alphatest_fragment.glsl.js +16 -7
  771. package/src/renderers/shaders/ShaderChunk/alphatest_pars_fragment.glsl.js +5 -5
  772. package/src/renderers/shaders/ShaderChunk/aomap_fragment.glsl.js +26 -18
  773. package/src/renderers/shaders/ShaderChunk/aomap_pars_fragment.glsl.js +8 -8
  774. package/src/renderers/shaders/ShaderChunk/batching_pars_vertex.glsl.js +19 -0
  775. package/src/renderers/shaders/ShaderChunk/batching_vertex.glsl.js +5 -0
  776. package/src/renderers/shaders/ShaderChunk/begin_vertex.glsl.js +9 -9
  777. package/src/renderers/shaders/ShaderChunk/beginnormal_vertex.glsl.js +9 -9
  778. package/src/renderers/shaders/ShaderChunk/bsdfs.glsl.js +33 -33
  779. package/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl.js +43 -42
  780. package/src/renderers/shaders/ShaderChunk/clearcoat_normal_fragment_begin.glsl.js +7 -7
  781. package/src/renderers/shaders/ShaderChunk/clearcoat_normal_fragment_maps.glsl.js +10 -10
  782. package/src/renderers/shaders/ShaderChunk/clearcoat_pars_fragment.glsl.js +21 -21
  783. package/src/renderers/shaders/ShaderChunk/clipping_planes_fragment.glsl.js +78 -33
  784. package/src/renderers/shaders/ShaderChunk/clipping_planes_pars_fragment.glsl.js +9 -9
  785. package/src/renderers/shaders/ShaderChunk/clipping_planes_pars_vertex.glsl.js +7 -7
  786. package/src/renderers/shaders/ShaderChunk/clipping_planes_vertex.glsl.js +7 -7
  787. package/src/renderers/shaders/ShaderChunk/color_fragment.glsl.js +11 -11
  788. package/src/renderers/shaders/ShaderChunk/color_pars_fragment.glsl.js +11 -11
  789. package/src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl.js +11 -11
  790. package/src/renderers/shaders/ShaderChunk/color_vertex.glsl.js +23 -23
  791. package/src/renderers/shaders/ShaderChunk/colorspace_fragment.glsl.js +3 -3
  792. package/src/renderers/shaders/ShaderChunk/colorspace_pars_fragment.glsl.js +44 -11
  793. package/src/renderers/shaders/ShaderChunk/common.glsl.js +147 -156
  794. package/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js +186 -191
  795. package/src/renderers/shaders/ShaderChunk/default_fragment.glsl.js +5 -5
  796. package/src/renderers/shaders/ShaderChunk/default_vertex.glsl.js +5 -5
  797. package/src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl.js +63 -36
  798. package/src/renderers/shaders/ShaderChunk/displacementmap_pars_vertex.glsl.js +9 -9
  799. package/src/renderers/shaders/ShaderChunk/displacementmap_vertex.glsl.js +7 -7
  800. package/src/renderers/shaders/ShaderChunk/dithering_fragment.glsl.js +7 -7
  801. package/src/renderers/shaders/ShaderChunk/dithering_pars_fragment.glsl.js +20 -20
  802. package/src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl.js +9 -9
  803. package/src/renderers/shaders/ShaderChunk/emissivemap_pars_fragment.glsl.js +7 -7
  804. package/src/renderers/shaders/ShaderChunk/envmap_common_pars_fragment.glsl.js +14 -14
  805. package/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +62 -62
  806. package/src/renderers/shaders/ShaderChunk/envmap_pars_fragment.glsl.js +21 -21
  807. package/src/renderers/shaders/ShaderChunk/envmap_pars_vertex.glsl.js +22 -22
  808. package/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js +69 -69
  809. package/src/renderers/shaders/ShaderChunk/envmap_vertex.glsl.js +37 -37
  810. package/src/renderers/shaders/ShaderChunk/fog_fragment.glsl.js +17 -17
  811. package/src/renderers/shaders/ShaderChunk/fog_pars_fragment.glsl.js +19 -19
  812. package/src/renderers/shaders/ShaderChunk/fog_pars_vertex.glsl.js +7 -7
  813. package/src/renderers/shaders/ShaderChunk/fog_vertex.glsl.js +7 -7
  814. package/src/renderers/shaders/ShaderChunk/gradientmap_pars_fragment.glsl.js +27 -27
  815. package/src/renderers/shaders/ShaderChunk/iridescence_fragment.glsl.js +120 -121
  816. package/src/renderers/shaders/ShaderChunk/iridescence_pars_fragment.glsl.js +14 -14
  817. package/src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl.js +10 -10
  818. package/src/renderers/shaders/ShaderChunk/lightmap_pars_fragment.glsl.js +8 -8
  819. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +202 -198
  820. package/src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js +13 -13
  821. package/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js +40 -40
  822. package/src/renderers/shaders/ShaderChunk/lights_lambert_fragment.glsl.js +5 -5
  823. package/src/renderers/shaders/ShaderChunk/lights_lambert_pars_fragment.glsl.js +28 -28
  824. package/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js +228 -223
  825. package/src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl.js +7 -7
  826. package/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl.js +32 -32
  827. package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +151 -146
  828. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +562 -560
  829. package/src/renderers/shaders/ShaderChunk/lights_toon_fragment.glsl.js +4 -4
  830. package/src/renderers/shaders/ShaderChunk/lights_toon_pars_fragment.glsl.js +26 -26
  831. package/src/renderers/shaders/ShaderChunk/logdepthbuf_fragment.glsl.js +9 -9
  832. package/src/renderers/shaders/ShaderChunk/logdepthbuf_pars_fragment.glsl.js +9 -9
  833. package/src/renderers/shaders/ShaderChunk/logdepthbuf_pars_vertex.glsl.js +16 -16
  834. package/src/renderers/shaders/ShaderChunk/logdepthbuf_vertex.glsl.js +22 -22
  835. package/src/renderers/shaders/ShaderChunk/map_fragment.glsl.js +21 -13
  836. package/src/renderers/shaders/ShaderChunk/map_pars_fragment.glsl.js +11 -11
  837. package/src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl.js +27 -27
  838. package/src/renderers/shaders/ShaderChunk/map_particle_pars_fragment.glsl.js +27 -27
  839. package/src/renderers/shaders/ShaderChunk/metalnessmap_fragment.glsl.js +12 -12
  840. package/src/renderers/shaders/ShaderChunk/metalnessmap_pars_fragment.glsl.js +7 -7
  841. package/src/renderers/shaders/ShaderChunk/morphcolor_vertex.glsl.js +24 -24
  842. package/src/renderers/shaders/ShaderChunk/morphnormal_vertex.glsl.js +27 -27
  843. package/src/renderers/shaders/ShaderChunk/morphtarget_pars_vertex.glsl.js +38 -38
  844. package/src/renderers/shaders/ShaderChunk/morphtarget_vertex.glsl.js +36 -36
  845. package/src/renderers/shaders/ShaderChunk/normal_fragment_begin.glsl.js +76 -76
  846. package/src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl.js +33 -33
  847. package/src/renderers/shaders/ShaderChunk/normal_pars_fragment.glsl.js +14 -14
  848. package/src/renderers/shaders/ShaderChunk/normal_pars_vertex.glsl.js +14 -14
  849. package/src/renderers/shaders/ShaderChunk/normal_vertex.glsl.js +14 -14
  850. package/src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl.js +43 -43
  851. package/src/renderers/shaders/ShaderChunk/occlusion_fragment.glsl.js +20 -0
  852. package/src/renderers/shaders/ShaderChunk/occlusion_pars_fragment.glsl.js +97 -0
  853. package/src/renderers/shaders/ShaderChunk/opaque_fragment.glsl.js +11 -11
  854. package/src/renderers/shaders/ShaderChunk/packing.glsl.js +68 -68
  855. package/src/renderers/shaders/ShaderChunk/premultiplied_alpha_fragment.glsl.js +8 -8
  856. package/src/renderers/shaders/ShaderChunk/project_vertex.glsl.js +19 -13
  857. package/src/renderers/shaders/ShaderChunk/roughnessmap_fragment.glsl.js +12 -12
  858. package/src/renderers/shaders/ShaderChunk/roughnessmap_pars_fragment.glsl.js +7 -7
  859. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +314 -314
  860. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl.js +68 -68
  861. package/src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js +68 -68
  862. package/src/renderers/shaders/ShaderChunk/shadowmask_pars_fragment.glsl.js +66 -66
  863. package/src/renderers/shaders/ShaderChunk/skinbase_vertex.glsl.js +10 -10
  864. package/src/renderers/shaders/ShaderChunk/skinning_pars_vertex.glsl.js +25 -33
  865. package/src/renderers/shaders/ShaderChunk/skinning_vertex.glsl.js +15 -15
  866. package/src/renderers/shaders/ShaderChunk/skinnormal_vertex.glsl.js +20 -20
  867. package/src/renderers/shaders/ShaderChunk/specularmap_fragment.glsl.js +14 -14
  868. package/src/renderers/shaders/ShaderChunk/specularmap_pars_fragment.glsl.js +7 -7
  869. package/src/renderers/shaders/ShaderChunk/tonemapping_fragment.glsl.js +7 -7
  870. package/src/renderers/shaders/ShaderChunk/tonemapping_pars_fragment.glsl.js +169 -77
  871. package/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js +36 -36
  872. package/src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js +201 -201
  873. package/src/renderers/shaders/ShaderChunk/uv_pars_fragment.glsl.js +119 -119
  874. package/src/renderers/shaders/ShaderChunk/uv_pars_vertex.glsl.js +145 -145
  875. package/src/renderers/shaders/ShaderChunk/uv_vertex.glsl.js +122 -122
  876. package/src/renderers/shaders/ShaderChunk/worldpos_vertex.glsl.js +21 -15
  877. package/src/renderers/shaders/ShaderChunk.js +274 -266
  878. package/src/renderers/shaders/ShaderLib/background.glsl.js +40 -32
  879. package/src/renderers/shaders/ShaderLib/backgroundCube.glsl.js +62 -62
  880. package/src/renderers/shaders/ShaderLib/cube.glsl.js +36 -36
  881. package/src/renderers/shaders/ShaderLib/depth.glsl.js +95 -94
  882. package/src/renderers/shaders/ShaderLib/distanceRGBA.glsl.js +76 -75
  883. package/src/renderers/shaders/ShaderLib/equirect.glsl.js +35 -35
  884. package/src/renderers/shaders/ShaderLib/linedashed.glsl.js +77 -75
  885. package/src/renderers/shaders/ShaderLib/meshbasic.glsl.js +117 -114
  886. package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +126 -122
  887. package/src/renderers/shaders/ShaderLib/meshmatcap.glsl.js +113 -109
  888. package/src/renderers/shaders/ShaderLib/meshnormal.glsl.js +89 -82
  889. package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +128 -124
  890. package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +226 -222
  891. package/src/renderers/shaders/ShaderLib/meshtoon.glsl.js +120 -116
  892. package/src/renderers/shaders/ShaderLib/points.glsl.js +88 -86
  893. package/src/renderers/shaders/ShaderLib/shadow.glsl.js +57 -54
  894. package/src/renderers/shaders/ShaderLib/sprite.glsl.js +81 -81
  895. package/src/renderers/shaders/ShaderLib/vsm.glsl.js +53 -53
  896. package/src/renderers/shaders/ShaderLib.js +367 -359
  897. package/src/renderers/shaders/UniformsLib.js +236 -230
  898. package/src/renderers/shaders/UniformsUtils.js +104 -104
  899. package/src/renderers/webgl/WebGLAnimation.js +53 -53
  900. package/src/renderers/webgl/WebGLAttributes.js +229 -195
  901. package/src/renderers/webgl/WebGLBackground.js +239 -247
  902. package/src/renderers/webgl/WebGLBindingStates.js +631 -631
  903. package/src/renderers/webgl/WebGLBufferRenderer.js +92 -61
  904. package/src/renderers/webgl/WebGLCapabilities.js +120 -120
  905. package/src/renderers/webgl/WebGLClipping.js +171 -171
  906. package/src/renderers/webgl/WebGLCubeMaps.js +99 -99
  907. package/src/renderers/webgl/WebGLCubeUVMaps.js +132 -130
  908. package/src/renderers/webgl/WebGLExtensions.js +97 -96
  909. package/src/renderers/webgl/WebGLGeometries.js +211 -207
  910. package/src/renderers/webgl/WebGLIndexedBufferRenderer.js +102 -71
  911. package/src/renderers/webgl/WebGLInfo.js +71 -71
  912. package/src/renderers/webgl/WebGLLights.js +590 -570
  913. package/src/renderers/webgl/WebGLMaterials.js +576 -567
  914. package/src/renderers/webgl/WebGLMorphtargets.js +300 -300
  915. package/src/renderers/webgl/WebGLObjects.js +92 -92
  916. package/src/renderers/webgl/WebGLProgram.js +1112 -1002
  917. package/src/renderers/webgl/WebGLPrograms.js +663 -625
  918. package/src/renderers/webgl/WebGLProperties.js +48 -48
  919. package/src/renderers/webgl/WebGLRenderLists.js +238 -238
  920. package/src/renderers/webgl/WebGLRenderStates.js +107 -107
  921. package/src/renderers/webgl/WebGLShader.js +12 -12
  922. package/src/renderers/webgl/WebGLShaderCache.js +124 -124
  923. package/src/renderers/webgl/WebGLShadowMap.js +424 -389
  924. package/src/renderers/webgl/WebGLState.js +1328 -1307
  925. package/src/renderers/webgl/WebGLTextures.js +2117 -2017
  926. package/src/renderers/webgl/WebGLUniforms.js +1156 -1146
  927. package/src/renderers/webgl/WebGLUniformsGroups.js +392 -413
  928. package/src/renderers/webgl/WebGLUtils.js +283 -278
  929. package/src/renderers/webxr/WebXRController.js +343 -343
  930. package/src/renderers/webxr/WebXRManager.js +840 -770
  931. package/src/scenes/Fog.js +38 -37
  932. package/src/scenes/FogExp2.js +35 -34
  933. package/src/scenes/Scene.js +63 -63
  934. package/src/textures/CanvasTexture.js +17 -17
  935. package/src/textures/CompressedArrayTexture.js +18 -18
  936. package/src/textures/CompressedCubeTexture.js +19 -0
  937. package/src/textures/CompressedTexture.js +28 -28
  938. package/src/textures/CubeTexture.js +33 -33
  939. package/src/textures/Data3DTexture.js +35 -35
  940. package/src/textures/DataArrayTexture.js +27 -27
  941. package/src/textures/DataTexture.js +22 -22
  942. package/src/textures/DepthTexture.js +58 -58
  943. package/src/textures/FramebufferTexture.js +23 -23
  944. package/src/textures/Source.js +127 -127
  945. package/src/textures/Texture.js +338 -338
  946. package/src/textures/VideoTexture.js +55 -55
  947. package/src/utils.js +91 -83
  948. package/build/three.js +0 -51661
  949. package/build/three.min.js +0 -7
  950. package/examples/jsm/nodes/accessors/ExtendedMaterialNode.js +0 -64
  951. package/examples/jsm/nodes/functions/BSDF/BRDF_BlinnPhong.js +0 -30
  952. package/examples/jsm/objects/GroundProjectedSkybox.js +0 -172
  953. package/examples/jsm/renderers/common/RenderTarget.js +0 -15
  954. package/examples/jsm/renderers/common/nodes/NodeRender.js +0 -302
  955. package/examples/jsm/renderers/webgpu/utils/WebGPUTextureMipmapUtils.js +0 -163
  956. package/src/lights/AmbientLightProbe.js +0 -21
  957. package/src/lights/HemisphereLightProbe.js +0 -30
@@ -1,2273 +1,2276 @@
1
- import {
2
- AddOperation,
3
- AnimationClip,
4
- Bone,
5
- BufferGeometry,
6
- Color,
7
- CustomBlending,
8
- TangentSpaceNormalMap,
9
- DoubleSide,
10
- DstAlphaFactor,
11
- Euler,
12
- FileLoader,
13
- Float32BufferAttribute,
14
- FrontSide,
15
- Interpolant,
16
- Loader,
17
- LoaderUtils,
18
- UniformsUtils,
19
- ShaderMaterial,
20
- MultiplyOperation,
21
- NearestFilter,
22
- NumberKeyframeTrack,
23
- OneMinusSrcAlphaFactor,
24
- Quaternion,
25
- QuaternionKeyframeTrack,
26
- RepeatWrapping,
27
- Skeleton,
28
- SkinnedMesh,
29
- SrcAlphaFactor,
30
- TextureLoader,
31
- Uint16BufferAttribute,
32
- Vector3,
33
- VectorKeyframeTrack,
34
- RGB_S3TC_DXT1_Format,
35
- RGB_PVRTC_4BPPV1_Format,
36
- RGB_PVRTC_2BPPV1_Format,
37
- RGB_ETC1_Format,
38
- RGB_ETC2_Format
39
- } from 'three';
40
- import { MMDToonShader } from '../shaders/MMDToonShader.js';
41
- import { TGALoader } from '../loaders/TGALoader.js';
42
- import { MMDParser } from '../libs/mmdparser.module.js';
43
-
44
- /**
45
- * Dependencies
46
- * - mmd-parser https://github.com/takahirox/mmd-parser
47
- * - TGALoader
48
- * - OutlineEffect
49
- *
50
- * MMDLoader creates Three.js Objects from MMD resources as
51
- * PMD, PMX, VMD, and VPD files.
52
- *
53
- * PMD/PMX is a model data format, VMD is a motion data format
54
- * VPD is a posing data format used in MMD(Miku Miku Dance).
55
- *
56
- * MMD official site
57
- * - https://sites.google.com/view/evpvp/
58
- *
59
- * PMD, VMD format (in Japanese)
60
- * - http://blog.goo.ne.jp/torisu_tetosuki/e/209ad341d3ece2b1b4df24abf619d6e4
61
- *
62
- * PMX format
63
- * - https://gist.github.com/felixjones/f8a06bd48f9da9a4539f
64
- *
65
- * TODO
66
- * - light motion in vmd support.
67
- * - SDEF support.
68
- * - uv/material/bone morphing support.
69
- * - more precise grant skinning support.
70
- * - shadow support.
71
- */
72
-
73
- /**
74
- * @param {THREE.LoadingManager} manager
75
- */
76
- class MMDLoader extends Loader {
77
-
78
- constructor( manager ) {
79
-
80
- super( manager );
81
-
82
- this.loader = new FileLoader( this.manager );
83
-
84
- this.parser = null; // lazy generation
85
- this.meshBuilder = new MeshBuilder( this.manager );
86
- this.animationBuilder = new AnimationBuilder();
87
-
88
- }
89
-
90
- /**
91
- * @param {string} animationPath
92
- * @return {MMDLoader}
93
- */
94
- setAnimationPath( animationPath ) {
95
-
96
- this.animationPath = animationPath;
97
- return this;
98
-
99
- }
100
-
101
- // Load MMD assets as Three.js Object
102
-
103
- /**
104
- * Loads Model file (.pmd or .pmx) as a SkinnedMesh.
105
- *
106
- * @param {string} url - url to Model(.pmd or .pmx) file
107
- * @param {function} onLoad
108
- * @param {function} onProgress
109
- * @param {function} onError
110
- */
111
- load( url, onLoad, onProgress, onError ) {
112
-
113
- const builder = this.meshBuilder.setCrossOrigin( this.crossOrigin );
114
-
115
- // resource path
116
-
117
- let resourcePath;
118
-
119
- if ( this.resourcePath !== '' ) {
120
-
121
- resourcePath = this.resourcePath;
122
-
123
- } else if ( this.path !== '' ) {
124
-
125
- resourcePath = this.path;
126
-
127
- } else {
128
-
129
- resourcePath = LoaderUtils.extractUrlBase( url );
130
-
131
- }
132
-
133
- const modelExtension = this._extractExtension( url ).toLowerCase();
134
-
135
- // Should I detect by seeing header?
136
- if ( modelExtension !== 'pmd' && modelExtension !== 'pmx' ) {
137
-
138
- if ( onError ) onError( new Error( 'THREE.MMDLoader: Unknown model file extension .' + modelExtension + '.' ) );
139
-
140
- return;
141
-
142
- }
143
-
144
- this[ modelExtension === 'pmd' ? 'loadPMD' : 'loadPMX' ]( url, function ( data ) {
145
-
146
- onLoad( builder.build( data, resourcePath, onProgress, onError ) );
147
-
148
- }, onProgress, onError );
149
-
150
- }
151
-
152
- /**
153
- * Loads Motion file(s) (.vmd) as a AnimationClip.
154
- * If two or more files are specified, they'll be merged.
155
- *
156
- * @param {string|Array<string>} url - url(s) to animation(.vmd) file(s)
157
- * @param {SkinnedMesh|THREE.Camera} object - tracks will be fitting to this object
158
- * @param {function} onLoad
159
- * @param {function} onProgress
160
- * @param {function} onError
161
- */
162
- loadAnimation( url, object, onLoad, onProgress, onError ) {
163
-
164
- const builder = this.animationBuilder;
165
-
166
- this.loadVMD( url, function ( vmd ) {
167
-
168
- onLoad( object.isCamera
169
- ? builder.buildCameraAnimation( vmd )
170
- : builder.build( vmd, object ) );
171
-
172
- }, onProgress, onError );
173
-
174
- }
175
-
176
- /**
177
- * Loads mode file and motion file(s) as an object containing
178
- * a SkinnedMesh and a AnimationClip.
179
- * Tracks of AnimationClip are fitting to the model.
180
- *
181
- * @param {string} modelUrl - url to Model(.pmd or .pmx) file
182
- * @param {string|Array{string}} vmdUrl - url(s) to animation(.vmd) file
183
- * @param {function} onLoad
184
- * @param {function} onProgress
185
- * @param {function} onError
186
- */
187
- loadWithAnimation( modelUrl, vmdUrl, onLoad, onProgress, onError ) {
188
-
189
- const scope = this;
190
-
191
- this.load( modelUrl, function ( mesh ) {
192
-
193
- scope.loadAnimation( vmdUrl, mesh, function ( animation ) {
194
-
195
- onLoad( {
196
- mesh: mesh,
197
- animation: animation
198
- } );
199
-
200
- }, onProgress, onError );
201
-
202
- }, onProgress, onError );
203
-
204
- }
205
-
206
- // Load MMD assets as Object data parsed by MMDParser
207
-
208
- /**
209
- * Loads .pmd file as an Object.
210
- *
211
- * @param {string} url - url to .pmd file
212
- * @param {function} onLoad
213
- * @param {function} onProgress
214
- * @param {function} onError
215
- */
216
- loadPMD( url, onLoad, onProgress, onError ) {
217
-
218
- const parser = this._getParser();
219
-
220
- this.loader
221
- .setMimeType( undefined )
222
- .setPath( this.path )
223
- .setResponseType( 'arraybuffer' )
224
- .setRequestHeader( this.requestHeader )
225
- .setWithCredentials( this.withCredentials )
226
- .load( url, function ( buffer ) {
227
-
228
- try {
229
-
230
- onLoad( parser.parsePmd( buffer, true ) );
231
-
232
- } catch ( e ) {
233
-
234
- if ( onError ) onError( e );
235
-
236
- }
237
-
238
- }, onProgress, onError );
239
-
240
- }
241
-
242
- /**
243
- * Loads .pmx file as an Object.
244
- *
245
- * @param {string} url - url to .pmx file
246
- * @param {function} onLoad
247
- * @param {function} onProgress
248
- * @param {function} onError
249
- */
250
- loadPMX( url, onLoad, onProgress, onError ) {
251
-
252
- const parser = this._getParser();
253
-
254
- this.loader
255
- .setMimeType( undefined )
256
- .setPath( this.path )
257
- .setResponseType( 'arraybuffer' )
258
- .setRequestHeader( this.requestHeader )
259
- .setWithCredentials( this.withCredentials )
260
- .load( url, function ( buffer ) {
261
-
262
- try {
263
-
264
- onLoad( parser.parsePmx( buffer, true ) );
265
-
266
- } catch ( e ) {
267
-
268
- if ( onError ) onError( e );
269
-
270
- }
271
-
272
- }, onProgress, onError );
273
-
274
- }
275
-
276
- /**
277
- * Loads .vmd file as an Object. If two or more files are specified
278
- * they'll be merged.
279
- *
280
- * @param {string|Array<string>} url - url(s) to .vmd file(s)
281
- * @param {function} onLoad
282
- * @param {function} onProgress
283
- * @param {function} onError
284
- */
285
- loadVMD( url, onLoad, onProgress, onError ) {
286
-
287
- const urls = Array.isArray( url ) ? url : [ url ];
288
-
289
- const vmds = [];
290
- const vmdNum = urls.length;
291
-
292
- const parser = this._getParser();
293
-
294
- this.loader
295
- .setMimeType( undefined )
296
- .setPath( this.animationPath )
297
- .setResponseType( 'arraybuffer' )
298
- .setRequestHeader( this.requestHeader )
299
- .setWithCredentials( this.withCredentials );
300
-
301
- for ( let i = 0, il = urls.length; i < il; i ++ ) {
302
-
303
- this.loader.load( urls[ i ], function ( buffer ) {
304
-
305
- try {
306
-
307
- vmds.push( parser.parseVmd( buffer, true ) );
308
-
309
- if ( vmds.length === vmdNum ) onLoad( parser.mergeVmds( vmds ) );
310
-
311
- } catch ( e ) {
312
-
313
- if ( onError ) onError( e );
314
-
315
- }
316
-
317
- }, onProgress, onError );
318
-
319
- }
320
-
321
- }
322
-
323
- /**
324
- * Loads .vpd file as an Object.
325
- *
326
- * @param {string} url - url to .vpd file
327
- * @param {boolean} isUnicode
328
- * @param {function} onLoad
329
- * @param {function} onProgress
330
- * @param {function} onError
331
- */
332
- loadVPD( url, isUnicode, onLoad, onProgress, onError ) {
333
-
334
- const parser = this._getParser();
335
-
336
- this.loader
337
- .setMimeType( isUnicode ? undefined : 'text/plain; charset=shift_jis' )
338
- .setPath( this.animationPath )
339
- .setResponseType( 'text' )
340
- .setRequestHeader( this.requestHeader )
341
- .setWithCredentials( this.withCredentials )
342
- .load( url, function ( text ) {
343
-
344
- try {
345
-
346
- onLoad( parser.parseVpd( text, true ) );
347
-
348
- } catch ( e ) {
349
-
350
- if ( onError ) onError( e );
351
-
352
- }
353
-
354
- }, onProgress, onError );
355
-
356
- }
357
-
358
- // private methods
359
-
360
- _extractExtension( url ) {
361
-
362
- const index = url.lastIndexOf( '.' );
363
- return index < 0 ? '' : url.slice( index + 1 );
364
-
365
- }
366
-
367
- _getParser() {
368
-
369
- if ( this.parser === null ) {
370
-
371
- this.parser = new MMDParser.Parser();
372
-
373
- }
374
-
375
- return this.parser;
376
-
377
- }
378
-
379
- }
380
-
381
- // Utilities
382
-
383
- /*
384
- * base64 encoded defalut toon textures toon00.bmp - toon10.bmp.
385
- * We don't need to request external toon image files.
386
- */
387
- const DEFAULT_TOON_TEXTURES = [
388
- 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=',
389
- 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAN0lEQVRYR+3WQREAMBACsZ5/bWiiMvgEBTt5cW37hjsBBAgQIECAwFwgyfYPCCBAgAABAgTWAh8aBHZBl14e8wAAAABJRU5ErkJggg==',
390
- 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAOUlEQVRYR+3WMREAMAwDsYY/yoDI7MLwIiP40+RJklfcCCBAgAABAgTqArfb/QMCCBAgQIAAgbbAB3z/e0F3js2cAAAAAElFTkSuQmCC',
391
- 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAN0lEQVRYR+3WQREAMBACsZ5/B5ilMvgEBTt5cW37hjsBBAgQIECAwFwgyfYPCCBAgAABAgTWAh81dWyx0gFwKAAAAABJRU5ErkJggg==',
392
- 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAOklEQVRYR+3WoREAMAwDsWb/UQtCy9wxTOQJ/oQ8SXKKGwEECBAgQIBAXeDt7f4BAQQIECBAgEBb4AOz8Hzx7WLY4wAAAABJRU5ErkJggg==',
393
- 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABPUlEQVRYR+1XwW7CMAy1+f9fZOMysSEOEweEOPRNdm3HbdOyIhAcklPrOs/PLy9RygBALxzcCDQFmgJNgaZAU6Ap0BR4PwX8gsRMVLssMRH5HcpzJEaWL7EVg9F1IHRlyqQohgVr4FGUlUcMJSjcUlDw0zvjeun70cLWmneoyf7NgBTQSniBTQQSuJAZsOnnaczjIMb5hCiuHKxokCrJfVnrctyZL0PkJAJe1HMil4nxeyi3Ypfn1kX51jpPvo/JeCNC4PhVdHdJw2XjBR8brF8PEIhNVn12AgP7uHsTBguBn53MUZCqv7Lp07Pn5k1Ro+uWmUNn7D+M57rtk7aG0Vo73xyF/fbFf0bPJjDXngnGocDTdFhygZjwUQrMNrDcmZlQT50VJ/g/UwNyHpu778+yW+/ksOz/BFo54P4AsUXMfRq7XWsAAAAASUVORK5CYII=',
394
- 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACMElEQVRYR+2Xv4pTQRTGf2dubhLdICiii2KnYKHVolhauKWPoGAnNr6BD6CvIVaihYuI2i1ia0BY0MZGRHQXjZj/mSPnnskfNWiWZUlzJ5k7M2cm833nO5Mziej2DWWJRUoCpQKlAntSQCqgw39/iUWAGmh37jrRnVsKlgpiqmkoGVABA7E57fvY+pJDdgKqF6HzFCSADkDq+F6AHABtQ+UMVE5D7zXod7fFNhTEckTbj5XQgHzNN+5tQvc5NG7C6BNkp6D3EmpXHDR+dQAjFLchW3VS9rlw3JBh+B7ys5Cf9z0GW1C/7P32AyBAOAz1q4jGliIH3YPuBnSfQX4OGreTIgEYQb/pBDtPnEQ4CivXYPAWBk13oHrB54yA9QuSn2H4AcKRpEILDt0BUzj+RLR1V5EqjD66NPRBVpLcQwjHoHYJOhsQv6U4mnzmrIXJCFr4LDwm/xBUoboG9XX4cc9VKdYoSA2yk5NQLJaKDUjTBoveG3Z2TElTxwjNK4M3LEZgUdDdruvcXzKBpStgp2NPiWi3ks9ZXxIoFVi+AvHLdc9TqtjL3/aYjpPlrzOcEnK62Szhimdd7xX232zFDTgtxezOu3WNMRLjiKgjtOhHVMd1loynVHvOgjuIIJMaELEqhJAV/RCSLbWTcfPFakFgFlALTRRvx+ok6Hlp/Q+v3fmx90bMyUzaEAhmM3KvHlXTL5DxnbGf/1M8RNNACLL5MNtPxP/mypJAqcDSFfgFhpYqWUzhTEAAAAAASUVORK5CYII=',
395
- 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=',
396
- 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=',
397
- 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=',
398
- 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII='
399
- ];
400
-
401
- const NON_ALPHA_CHANNEL_FORMATS = [
402
- RGB_S3TC_DXT1_Format,
403
- RGB_PVRTC_4BPPV1_Format,
404
- RGB_PVRTC_2BPPV1_Format,
405
- RGB_ETC1_Format,
406
- RGB_ETC2_Format
407
- ];
408
-
409
- // Builders. They build Three.js object from Object data parsed by MMDParser.
410
-
411
- /**
412
- * @param {THREE.LoadingManager} manager
413
- */
414
- class MeshBuilder {
415
-
416
- constructor( manager ) {
417
-
418
- this.crossOrigin = 'anonymous';
419
- this.geometryBuilder = new GeometryBuilder();
420
- this.materialBuilder = new MaterialBuilder( manager );
421
-
422
- }
423
-
424
- /**
425
- * @param {string} crossOrigin
426
- * @return {MeshBuilder}
427
- */
428
- setCrossOrigin( crossOrigin ) {
429
-
430
- this.crossOrigin = crossOrigin;
431
- return this;
432
-
433
- }
434
-
435
- /**
436
- * @param {Object} data - parsed PMD/PMX data
437
- * @param {string} resourcePath
438
- * @param {function} onProgress
439
- * @param {function} onError
440
- * @return {SkinnedMesh}
441
- */
442
- build( data, resourcePath, onProgress, onError ) {
443
-
444
- const geometry = this.geometryBuilder.build( data );
445
- const material = this.materialBuilder
446
- .setCrossOrigin( this.crossOrigin )
447
- .setResourcePath( resourcePath )
448
- .build( data, geometry, onProgress, onError );
449
-
450
- const mesh = new SkinnedMesh( geometry, material );
451
-
452
- const skeleton = new Skeleton( initBones( mesh ) );
453
- mesh.bind( skeleton );
454
-
455
- // console.log( mesh ); // for console debug
456
-
457
- return mesh;
458
-
459
- }
460
-
461
- }
462
-
463
- // TODO: Try to remove this function
464
-
465
- function initBones( mesh ) {
466
-
467
- const geometry = mesh.geometry;
468
-
469
- const bones = [];
470
-
471
- if ( geometry && geometry.bones !== undefined ) {
472
-
473
- // first, create array of 'Bone' objects from geometry data
474
-
475
- for ( let i = 0, il = geometry.bones.length; i < il; i ++ ) {
476
-
477
- const gbone = geometry.bones[ i ];
478
-
479
- // create new 'Bone' object
480
-
481
- const bone = new Bone();
482
- bones.push( bone );
483
-
484
- // apply values
485
-
486
- bone.name = gbone.name;
487
- bone.position.fromArray( gbone.pos );
488
- bone.quaternion.fromArray( gbone.rotq );
489
- if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl );
490
-
491
- }
492
-
493
- // second, create bone hierarchy
494
-
495
- for ( let i = 0, il = geometry.bones.length; i < il; i ++ ) {
496
-
497
- const gbone = geometry.bones[ i ];
498
-
499
- if ( ( gbone.parent !== - 1 ) && ( gbone.parent !== null ) && ( bones[ gbone.parent ] !== undefined ) ) {
500
-
501
- // subsequent bones in the hierarchy
502
-
503
- bones[ gbone.parent ].add( bones[ i ] );
504
-
505
- } else {
506
-
507
- // topmost bone, immediate child of the skinned mesh
508
-
509
- mesh.add( bones[ i ] );
510
-
511
- }
512
-
513
- }
514
-
515
- }
516
-
517
- // now the bones are part of the scene graph and children of the skinned mesh.
518
- // let's update the corresponding matrices
519
-
520
- mesh.updateMatrixWorld( true );
521
-
522
- return bones;
523
-
524
- }
525
-
526
- //
527
-
528
- class GeometryBuilder {
529
-
530
- /**
531
- * @param {Object} data - parsed PMD/PMX data
532
- * @return {BufferGeometry}
533
- */
534
- build( data ) {
535
-
536
- // for geometry
537
- const positions = [];
538
- const uvs = [];
539
- const normals = [];
540
-
541
- const indices = [];
542
-
543
- const groups = [];
544
-
545
- const bones = [];
546
- const skinIndices = [];
547
- const skinWeights = [];
548
-
549
- const morphTargets = [];
550
- const morphPositions = [];
551
-
552
- const iks = [];
553
- const grants = [];
554
-
555
- const rigidBodies = [];
556
- const constraints = [];
557
-
558
- // for work
559
- let offset = 0;
560
- const boneTypeTable = {};
561
-
562
- // positions, normals, uvs, skinIndices, skinWeights
563
-
564
- for ( let i = 0; i < data.metadata.vertexCount; i ++ ) {
565
-
566
- const v = data.vertices[ i ];
567
-
568
- for ( let j = 0, jl = v.position.length; j < jl; j ++ ) {
569
-
570
- positions.push( v.position[ j ] );
571
-
572
- }
573
-
574
- for ( let j = 0, jl = v.normal.length; j < jl; j ++ ) {
575
-
576
- normals.push( v.normal[ j ] );
577
-
578
- }
579
-
580
- for ( let j = 0, jl = v.uv.length; j < jl; j ++ ) {
581
-
582
- uvs.push( v.uv[ j ] );
583
-
584
- }
585
-
586
- for ( let j = 0; j < 4; j ++ ) {
587
-
588
- skinIndices.push( v.skinIndices.length - 1 >= j ? v.skinIndices[ j ] : 0.0 );
589
-
590
- }
591
-
592
- for ( let j = 0; j < 4; j ++ ) {
593
-
594
- skinWeights.push( v.skinWeights.length - 1 >= j ? v.skinWeights[ j ] : 0.0 );
595
-
596
- }
597
-
598
- }
599
-
600
- // indices
601
-
602
- for ( let i = 0; i < data.metadata.faceCount; i ++ ) {
603
-
604
- const face = data.faces[ i ];
605
-
606
- for ( let j = 0, jl = face.indices.length; j < jl; j ++ ) {
607
-
608
- indices.push( face.indices[ j ] );
609
-
610
- }
611
-
612
- }
613
-
614
- // groups
615
-
616
- for ( let i = 0; i < data.metadata.materialCount; i ++ ) {
617
-
618
- const material = data.materials[ i ];
619
-
620
- groups.push( {
621
- offset: offset * 3,
622
- count: material.faceCount * 3
623
- } );
624
-
625
- offset += material.faceCount;
626
-
627
- }
628
-
629
- // bones
630
-
631
- for ( let i = 0; i < data.metadata.rigidBodyCount; i ++ ) {
632
-
633
- const body = data.rigidBodies[ i ];
634
- let value = boneTypeTable[ body.boneIndex ];
635
-
636
- // keeps greater number if already value is set without any special reasons
637
- value = value === undefined ? body.type : Math.max( body.type, value );
638
-
639
- boneTypeTable[ body.boneIndex ] = value;
640
-
641
- }
642
-
643
- for ( let i = 0; i < data.metadata.boneCount; i ++ ) {
644
-
645
- const boneData = data.bones[ i ];
646
-
647
- const bone = {
648
- index: i,
649
- transformationClass: boneData.transformationClass,
650
- parent: boneData.parentIndex,
651
- name: boneData.name,
652
- pos: boneData.position.slice( 0, 3 ),
653
- rotq: [ 0, 0, 0, 1 ],
654
- scl: [ 1, 1, 1 ],
655
- rigidBodyType: boneTypeTable[ i ] !== undefined ? boneTypeTable[ i ] : - 1
656
- };
657
-
658
- if ( bone.parent !== - 1 ) {
659
-
660
- bone.pos[ 0 ] -= data.bones[ bone.parent ].position[ 0 ];
661
- bone.pos[ 1 ] -= data.bones[ bone.parent ].position[ 1 ];
662
- bone.pos[ 2 ] -= data.bones[ bone.parent ].position[ 2 ];
663
-
664
- }
665
-
666
- bones.push( bone );
667
-
668
- }
669
-
670
- // iks
671
-
672
- // TODO: remove duplicated codes between PMD and PMX
673
- if ( data.metadata.format === 'pmd' ) {
674
-
675
- for ( let i = 0; i < data.metadata.ikCount; i ++ ) {
676
-
677
- const ik = data.iks[ i ];
678
-
679
- const param = {
680
- target: ik.target,
681
- effector: ik.effector,
682
- iteration: ik.iteration,
683
- maxAngle: ik.maxAngle * 4,
684
- links: []
685
- };
686
-
687
- for ( let j = 0, jl = ik.links.length; j < jl; j ++ ) {
688
-
689
- const link = {};
690
- link.index = ik.links[ j ].index;
691
- link.enabled = true;
692
-
693
- if ( data.bones[ link.index ].name.indexOf( 'ひざ' ) >= 0 ) {
694
-
695
- link.limitation = new Vector3( 1.0, 0.0, 0.0 );
696
-
697
- }
698
-
699
- param.links.push( link );
700
-
701
- }
702
-
703
- iks.push( param );
704
-
705
- }
706
-
707
- } else {
708
-
709
- for ( let i = 0; i < data.metadata.boneCount; i ++ ) {
710
-
711
- const ik = data.bones[ i ].ik;
712
-
713
- if ( ik === undefined ) continue;
714
-
715
- const param = {
716
- target: i,
717
- effector: ik.effector,
718
- iteration: ik.iteration,
719
- maxAngle: ik.maxAngle,
720
- links: []
721
- };
722
-
723
- for ( let j = 0, jl = ik.links.length; j < jl; j ++ ) {
724
-
725
- const link = {};
726
- link.index = ik.links[ j ].index;
727
- link.enabled = true;
728
-
729
- if ( ik.links[ j ].angleLimitation === 1 ) {
730
-
731
- // Revert if rotationMin/Max doesn't work well
732
- // link.limitation = new Vector3( 1.0, 0.0, 0.0 );
733
-
734
- const rotationMin = ik.links[ j ].lowerLimitationAngle;
735
- const rotationMax = ik.links[ j ].upperLimitationAngle;
736
-
737
- // Convert Left to Right coordinate by myself because
738
- // MMDParser doesn't convert. It's a MMDParser's bug
739
-
740
- const tmp1 = - rotationMax[ 0 ];
741
- const tmp2 = - rotationMax[ 1 ];
742
- rotationMax[ 0 ] = - rotationMin[ 0 ];
743
- rotationMax[ 1 ] = - rotationMin[ 1 ];
744
- rotationMin[ 0 ] = tmp1;
745
- rotationMin[ 1 ] = tmp2;
746
-
747
- link.rotationMin = new Vector3().fromArray( rotationMin );
748
- link.rotationMax = new Vector3().fromArray( rotationMax );
749
-
750
- }
751
-
752
- param.links.push( link );
753
-
754
- }
755
-
756
- iks.push( param );
757
-
758
- // Save the reference even from bone data for efficiently
759
- // simulating PMX animation system
760
- bones[ i ].ik = param;
761
-
762
- }
763
-
764
- }
765
-
766
- // grants
767
-
768
- if ( data.metadata.format === 'pmx' ) {
769
-
770
- // bone index -> grant entry map
771
- const grantEntryMap = {};
772
-
773
- for ( let i = 0; i < data.metadata.boneCount; i ++ ) {
774
-
775
- const boneData = data.bones[ i ];
776
- const grant = boneData.grant;
777
-
778
- if ( grant === undefined ) continue;
779
-
780
- const param = {
781
- index: i,
782
- parentIndex: grant.parentIndex,
783
- ratio: grant.ratio,
784
- isLocal: grant.isLocal,
785
- affectRotation: grant.affectRotation,
786
- affectPosition: grant.affectPosition,
787
- transformationClass: boneData.transformationClass
788
- };
789
-
790
- grantEntryMap[ i ] = { parent: null, children: [], param: param, visited: false };
791
-
792
- }
793
-
794
- const rootEntry = { parent: null, children: [], param: null, visited: false };
795
-
796
- // Build a tree representing grant hierarchy
797
-
798
- for ( const boneIndex in grantEntryMap ) {
799
-
800
- const grantEntry = grantEntryMap[ boneIndex ];
801
- const parentGrantEntry = grantEntryMap[ grantEntry.parentIndex ] || rootEntry;
802
-
803
- grantEntry.parent = parentGrantEntry;
804
- parentGrantEntry.children.push( grantEntry );
805
-
806
- }
807
-
808
- // Sort grant parameters from parents to children because
809
- // grant uses parent's transform that parent's grant is already applied
810
- // so grant should be applied in order from parents to children
811
-
812
- function traverse( entry ) {
813
-
814
- if ( entry.param ) {
815
-
816
- grants.push( entry.param );
817
-
818
- // Save the reference even from bone data for efficiently
819
- // simulating PMX animation system
820
- bones[ entry.param.index ].grant = entry.param;
821
-
822
- }
823
-
824
- entry.visited = true;
825
-
826
- for ( let i = 0, il = entry.children.length; i < il; i ++ ) {
827
-
828
- const child = entry.children[ i ];
829
-
830
- // Cut off a loop if exists. (Is a grant loop invalid?)
831
- if ( ! child.visited ) traverse( child );
832
-
833
- }
834
-
835
- }
836
-
837
- traverse( rootEntry );
838
-
839
- }
840
-
841
- // morph
842
-
843
- function updateAttributes( attribute, morph, ratio ) {
844
-
845
- for ( let i = 0; i < morph.elementCount; i ++ ) {
846
-
847
- const element = morph.elements[ i ];
848
-
849
- let index;
850
-
851
- if ( data.metadata.format === 'pmd' ) {
852
-
853
- index = data.morphs[ 0 ].elements[ element.index ].index;
854
-
855
- } else {
856
-
857
- index = element.index;
858
-
859
- }
860
-
861
- attribute.array[ index * 3 + 0 ] += element.position[ 0 ] * ratio;
862
- attribute.array[ index * 3 + 1 ] += element.position[ 1 ] * ratio;
863
- attribute.array[ index * 3 + 2 ] += element.position[ 2 ] * ratio;
864
-
865
- }
866
-
867
- }
868
-
869
- for ( let i = 0; i < data.metadata.morphCount; i ++ ) {
870
-
871
- const morph = data.morphs[ i ];
872
- const params = { name: morph.name };
873
-
874
- const attribute = new Float32BufferAttribute( data.metadata.vertexCount * 3, 3 );
875
- attribute.name = morph.name;
876
-
877
- for ( let j = 0; j < data.metadata.vertexCount * 3; j ++ ) {
878
-
879
- attribute.array[ j ] = positions[ j ];
880
-
881
- }
882
-
883
- if ( data.metadata.format === 'pmd' ) {
884
-
885
- if ( i !== 0 ) {
886
-
887
- updateAttributes( attribute, morph, 1.0 );
888
-
889
- }
890
-
891
- } else {
892
-
893
- if ( morph.type === 0 ) { // group
894
-
895
- for ( let j = 0; j < morph.elementCount; j ++ ) {
896
-
897
- const morph2 = data.morphs[ morph.elements[ j ].index ];
898
- const ratio = morph.elements[ j ].ratio;
899
-
900
- if ( morph2.type === 1 ) {
901
-
902
- updateAttributes( attribute, morph2, ratio );
903
-
904
- } else {
905
-
906
- // TODO: implement
907
-
908
- }
909
-
910
- }
911
-
912
- } else if ( morph.type === 1 ) { // vertex
913
-
914
- updateAttributes( attribute, morph, 1.0 );
915
-
916
- } else if ( morph.type === 2 ) { // bone
917
-
918
- // TODO: implement
919
-
920
- } else if ( morph.type === 3 ) { // uv
921
-
922
- // TODO: implement
923
-
924
- } else if ( morph.type === 4 ) { // additional uv1
925
-
926
- // TODO: implement
927
-
928
- } else if ( morph.type === 5 ) { // additional uv2
929
-
930
- // TODO: implement
931
-
932
- } else if ( morph.type === 6 ) { // additional uv3
933
-
934
- // TODO: implement
935
-
936
- } else if ( morph.type === 7 ) { // additional uv4
937
-
938
- // TODO: implement
939
-
940
- } else if ( morph.type === 8 ) { // material
941
-
942
- // TODO: implement
943
-
944
- }
945
-
946
- }
947
-
948
- morphTargets.push( params );
949
- morphPositions.push( attribute );
950
-
951
- }
952
-
953
- // rigid bodies from rigidBodies field.
954
-
955
- for ( let i = 0; i < data.metadata.rigidBodyCount; i ++ ) {
956
-
957
- const rigidBody = data.rigidBodies[ i ];
958
- const params = {};
959
-
960
- for ( const key in rigidBody ) {
961
-
962
- params[ key ] = rigidBody[ key ];
963
-
964
- }
965
-
966
- /*
967
- * RigidBody position parameter in PMX seems global position
968
- * while the one in PMD seems offset from corresponding bone.
969
- * So unify being offset.
970
- */
971
- if ( data.metadata.format === 'pmx' ) {
972
-
973
- if ( params.boneIndex !== - 1 ) {
974
-
975
- const bone = data.bones[ params.boneIndex ];
976
- params.position[ 0 ] -= bone.position[ 0 ];
977
- params.position[ 1 ] -= bone.position[ 1 ];
978
- params.position[ 2 ] -= bone.position[ 2 ];
979
-
980
- }
981
-
982
- }
983
-
984
- rigidBodies.push( params );
985
-
986
- }
987
-
988
- // constraints from constraints field.
989
-
990
- for ( let i = 0; i < data.metadata.constraintCount; i ++ ) {
991
-
992
- const constraint = data.constraints[ i ];
993
- const params = {};
994
-
995
- for ( const key in constraint ) {
996
-
997
- params[ key ] = constraint[ key ];
998
-
999
- }
1000
-
1001
- const bodyA = rigidBodies[ params.rigidBodyIndex1 ];
1002
- const bodyB = rigidBodies[ params.rigidBodyIndex2 ];
1003
-
1004
- // Refer to http://www20.atpages.jp/katwat/wp/?p=4135
1005
- if ( bodyA.type !== 0 && bodyB.type === 2 ) {
1006
-
1007
- if ( bodyA.boneIndex !== - 1 && bodyB.boneIndex !== - 1 &&
1008
- data.bones[ bodyB.boneIndex ].parentIndex === bodyA.boneIndex ) {
1009
-
1010
- bodyB.type = 1;
1011
-
1012
- }
1013
-
1014
- }
1015
-
1016
- constraints.push( params );
1017
-
1018
- }
1019
-
1020
- // build BufferGeometry.
1021
-
1022
- const geometry = new BufferGeometry();
1023
-
1024
- geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
1025
- geometry.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
1026
- geometry.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
1027
- geometry.setAttribute( 'skinIndex', new Uint16BufferAttribute( skinIndices, 4 ) );
1028
- geometry.setAttribute( 'skinWeight', new Float32BufferAttribute( skinWeights, 4 ) );
1029
- geometry.setIndex( indices );
1030
-
1031
- for ( let i = 0, il = groups.length; i < il; i ++ ) {
1032
-
1033
- geometry.addGroup( groups[ i ].offset, groups[ i ].count, i );
1034
-
1035
- }
1036
-
1037
- geometry.bones = bones;
1038
-
1039
- geometry.morphTargets = morphTargets;
1040
- geometry.morphAttributes.position = morphPositions;
1041
- geometry.morphTargetsRelative = false;
1042
-
1043
- geometry.userData.MMD = {
1044
- bones: bones,
1045
- iks: iks,
1046
- grants: grants,
1047
- rigidBodies: rigidBodies,
1048
- constraints: constraints,
1049
- format: data.metadata.format
1050
- };
1051
-
1052
- geometry.computeBoundingSphere();
1053
-
1054
- return geometry;
1055
-
1056
- }
1057
-
1058
- }
1059
-
1060
- //
1061
-
1062
- /**
1063
- * @param {THREE.LoadingManager} manager
1064
- */
1065
- class MaterialBuilder {
1066
-
1067
- constructor( manager ) {
1068
-
1069
- this.manager = manager;
1070
-
1071
- this.textureLoader = new TextureLoader( this.manager );
1072
- this.tgaLoader = null; // lazy generation
1073
-
1074
- this.crossOrigin = 'anonymous';
1075
- this.resourcePath = undefined;
1076
-
1077
- }
1078
-
1079
- /**
1080
- * @param {string} crossOrigin
1081
- * @return {MaterialBuilder}
1082
- */
1083
- setCrossOrigin( crossOrigin ) {
1084
-
1085
- this.crossOrigin = crossOrigin;
1086
- return this;
1087
-
1088
- }
1089
-
1090
- /**
1091
- * @param {string} resourcePath
1092
- * @return {MaterialBuilder}
1093
- */
1094
- setResourcePath( resourcePath ) {
1095
-
1096
- this.resourcePath = resourcePath;
1097
- return this;
1098
-
1099
- }
1100
-
1101
- /**
1102
- * @param {Object} data - parsed PMD/PMX data
1103
- * @param {BufferGeometry} geometry - some properties are dependend on geometry
1104
- * @param {function} onProgress
1105
- * @param {function} onError
1106
- * @return {Array<MMDToonMaterial>}
1107
- */
1108
- build( data, geometry /*, onProgress, onError */ ) {
1109
-
1110
- const materials = [];
1111
-
1112
- const textures = {};
1113
-
1114
- this.textureLoader.setCrossOrigin( this.crossOrigin );
1115
-
1116
- // materials
1117
-
1118
- for ( let i = 0; i < data.metadata.materialCount; i ++ ) {
1119
-
1120
- const material = data.materials[ i ];
1121
-
1122
- const params = { userData: { MMD: {} } };
1123
-
1124
- if ( material.name !== undefined ) params.name = material.name;
1125
-
1126
- /*
1127
- * Color
1128
- *
1129
- * MMD MMDToonMaterial
1130
- * ambient - emissive * a
1131
- * (a = 1.0 without map texture or 0.2 with map texture)
1132
- *
1133
- * MMDToonMaterial doesn't have ambient. Set it to emissive instead.
1134
- * It'll be too bright if material has map texture so using coef 0.2.
1135
- */
1136
- params.diffuse = new Color().fromArray( material.diffuse );
1137
- params.opacity = material.diffuse[ 3 ];
1138
- params.specular = new Color().fromArray( material.specular );
1139
- params.shininess = material.shininess;
1140
- params.emissive = new Color().fromArray( material.ambient );
1141
- params.transparent = params.opacity !== 1.0;
1142
-
1143
- params.diffuse.convertSRGBToLinear();
1144
- params.specular.convertSRGBToLinear();
1145
- params.emissive.convertSRGBToLinear();
1146
-
1147
- //
1148
-
1149
- params.fog = true;
1150
-
1151
- // blend
1152
-
1153
- params.blending = CustomBlending;
1154
- params.blendSrc = SrcAlphaFactor;
1155
- params.blendDst = OneMinusSrcAlphaFactor;
1156
- params.blendSrcAlpha = SrcAlphaFactor;
1157
- params.blendDstAlpha = DstAlphaFactor;
1158
-
1159
- // side
1160
-
1161
- if ( data.metadata.format === 'pmx' && ( material.flag & 0x1 ) === 1 ) {
1162
-
1163
- params.side = DoubleSide;
1164
-
1165
- } else {
1166
-
1167
- params.side = params.opacity === 1.0 ? FrontSide : DoubleSide;
1168
-
1169
- }
1170
-
1171
- if ( data.metadata.format === 'pmd' ) {
1172
-
1173
- // map, matcap
1174
-
1175
- if ( material.fileName ) {
1176
-
1177
- const fileName = material.fileName;
1178
- const fileNames = fileName.split( '*' );
1179
-
1180
- // fileNames[ 0 ]: mapFileName
1181
- // fileNames[ 1 ]: matcapFileName( optional )
1182
-
1183
- params.map = this._loadTexture( fileNames[ 0 ], textures );
1184
-
1185
- if ( fileNames.length > 1 ) {
1186
-
1187
- const extension = fileNames[ 1 ].slice( - 4 ).toLowerCase();
1188
-
1189
- params.matcap = this._loadTexture(
1190
- fileNames[ 1 ],
1191
- textures
1192
- );
1193
-
1194
- params.matcapCombine = extension === '.sph'
1195
- ? MultiplyOperation
1196
- : AddOperation;
1197
-
1198
- }
1199
-
1200
- }
1201
-
1202
- // gradientMap
1203
-
1204
- const toonFileName = ( material.toonIndex === - 1 )
1205
- ? 'toon00.bmp'
1206
- : data.toonTextures[ material.toonIndex ].fileName;
1207
-
1208
- params.gradientMap = this._loadTexture(
1209
- toonFileName,
1210
- textures,
1211
- {
1212
- isToonTexture: true,
1213
- isDefaultToonTexture: this._isDefaultToonTexture( toonFileName )
1214
- }
1215
- );
1216
-
1217
- // parameters for OutlineEffect
1218
-
1219
- params.userData.outlineParameters = {
1220
- thickness: material.edgeFlag === 1 ? 0.003 : 0.0,
1221
- color: [ 0, 0, 0 ],
1222
- alpha: 1.0,
1223
- visible: material.edgeFlag === 1
1224
- };
1225
-
1226
- } else {
1227
-
1228
- // map
1229
-
1230
- if ( material.textureIndex !== - 1 ) {
1231
-
1232
- params.map = this._loadTexture( data.textures[ material.textureIndex ], textures );
1233
-
1234
- // Since PMX spec don't have standard to list map files except color map and env map,
1235
- // we need to save file name for further mapping, like matching normal map file names after model loaded.
1236
- // ref: https://gist.github.com/felixjones/f8a06bd48f9da9a4539f#texture
1237
- params.userData.MMD.mapFileName = data.textures[ material.textureIndex ];
1238
-
1239
- }
1240
-
1241
- // matcap TODO: support m.envFlag === 3
1242
-
1243
- if ( material.envTextureIndex !== - 1 && ( material.envFlag === 1 || material.envFlag == 2 ) ) {
1244
-
1245
- params.matcap = this._loadTexture(
1246
- data.textures[ material.envTextureIndex ],
1247
- textures
1248
- );
1249
-
1250
- // Same as color map above, keep file name in userData for further usage.
1251
- params.userData.MMD.matcapFileName = data.textures[ material.envTextureIndex ];
1252
-
1253
- params.matcapCombine = material.envFlag === 1
1254
- ? MultiplyOperation
1255
- : AddOperation;
1256
-
1257
- }
1258
-
1259
- // gradientMap
1260
-
1261
- let toonFileName, isDefaultToon;
1262
-
1263
- if ( material.toonIndex === - 1 || material.toonFlag !== 0 ) {
1264
-
1265
- toonFileName = 'toon' + ( '0' + ( material.toonIndex + 1 ) ).slice( - 2 ) + '.bmp';
1266
- isDefaultToon = true;
1267
-
1268
- } else {
1269
-
1270
- toonFileName = data.textures[ material.toonIndex ];
1271
- isDefaultToon = false;
1272
-
1273
- }
1274
-
1275
- params.gradientMap = this._loadTexture(
1276
- toonFileName,
1277
- textures,
1278
- {
1279
- isToonTexture: true,
1280
- isDefaultToonTexture: isDefaultToon
1281
- }
1282
- );
1283
-
1284
- // parameters for OutlineEffect
1285
- params.userData.outlineParameters = {
1286
- thickness: material.edgeSize / 300, // TODO: better calculation?
1287
- color: material.edgeColor.slice( 0, 3 ),
1288
- alpha: material.edgeColor[ 3 ],
1289
- visible: ( material.flag & 0x10 ) !== 0 && material.edgeSize > 0.0
1290
- };
1291
-
1292
- }
1293
-
1294
- if ( params.map !== undefined ) {
1295
-
1296
- if ( ! params.transparent ) {
1297
-
1298
- this._checkImageTransparency( params.map, geometry, i );
1299
-
1300
- }
1301
-
1302
- params.emissive.multiplyScalar( 0.2 );
1303
-
1304
- }
1305
-
1306
- materials.push( new MMDToonMaterial( params ) );
1307
-
1308
- }
1309
-
1310
- if ( data.metadata.format === 'pmx' ) {
1311
-
1312
- // set transparent true if alpha morph is defined.
1313
-
1314
- function checkAlphaMorph( elements, materials ) {
1315
-
1316
- for ( let i = 0, il = elements.length; i < il; i ++ ) {
1317
-
1318
- const element = elements[ i ];
1319
-
1320
- if ( element.index === - 1 ) continue;
1321
-
1322
- const material = materials[ element.index ];
1323
-
1324
- if ( material.opacity !== element.diffuse[ 3 ] ) {
1325
-
1326
- material.transparent = true;
1327
-
1328
- }
1329
-
1330
- }
1331
-
1332
- }
1333
-
1334
- for ( let i = 0, il = data.morphs.length; i < il; i ++ ) {
1335
-
1336
- const morph = data.morphs[ i ];
1337
- const elements = morph.elements;
1338
-
1339
- if ( morph.type === 0 ) {
1340
-
1341
- for ( let j = 0, jl = elements.length; j < jl; j ++ ) {
1342
-
1343
- const morph2 = data.morphs[ elements[ j ].index ];
1344
-
1345
- if ( morph2.type !== 8 ) continue;
1346
-
1347
- checkAlphaMorph( morph2.elements, materials );
1348
-
1349
- }
1350
-
1351
- } else if ( morph.type === 8 ) {
1352
-
1353
- checkAlphaMorph( elements, materials );
1354
-
1355
- }
1356
-
1357
- }
1358
-
1359
- }
1360
-
1361
- return materials;
1362
-
1363
- }
1364
-
1365
- // private methods
1366
-
1367
- _getTGALoader() {
1368
-
1369
- if ( this.tgaLoader === null ) {
1370
-
1371
- if ( TGALoader === undefined ) {
1372
-
1373
- throw new Error( 'THREE.MMDLoader: Import TGALoader' );
1374
-
1375
- }
1376
-
1377
- this.tgaLoader = new TGALoader( this.manager );
1378
-
1379
- }
1380
-
1381
- return this.tgaLoader;
1382
-
1383
- }
1384
-
1385
- _isDefaultToonTexture( name ) {
1386
-
1387
- if ( name.length !== 10 ) return false;
1388
-
1389
- return /toon(10|0[0-9])\.bmp/.test( name );
1390
-
1391
- }
1392
-
1393
- _loadTexture( filePath, textures, params, onProgress, onError ) {
1394
-
1395
- params = params || {};
1396
-
1397
- const scope = this;
1398
-
1399
- let fullPath;
1400
-
1401
- if ( params.isDefaultToonTexture === true ) {
1402
-
1403
- let index;
1404
-
1405
- try {
1406
-
1407
- index = parseInt( filePath.match( /toon([0-9]{2})\.bmp$/ )[ 1 ] );
1408
-
1409
- } catch ( e ) {
1410
-
1411
- console.warn( 'THREE.MMDLoader: ' + filePath + ' seems like a '
1412
- + 'not right default texture path. Using toon00.bmp instead.' );
1413
-
1414
- index = 0;
1415
-
1416
- }
1417
-
1418
- fullPath = DEFAULT_TOON_TEXTURES[ index ];
1419
-
1420
- } else {
1421
-
1422
- fullPath = this.resourcePath + filePath;
1423
-
1424
- }
1425
-
1426
- if ( textures[ fullPath ] !== undefined ) return textures[ fullPath ];
1427
-
1428
- let loader = this.manager.getHandler( fullPath );
1429
-
1430
- if ( loader === null ) {
1431
-
1432
- loader = ( filePath.slice( - 4 ).toLowerCase() === '.tga' )
1433
- ? this._getTGALoader()
1434
- : this.textureLoader;
1435
-
1436
- }
1437
-
1438
- const texture = loader.load( fullPath, function ( t ) {
1439
-
1440
- // MMD toon texture is Axis-Y oriented
1441
- // but Three.js gradient map is Axis-X oriented.
1442
- // So here replaces the toon texture image with the rotated one.
1443
- if ( params.isToonTexture === true ) {
1444
-
1445
- t.image = scope._getRotatedImage( t.image );
1446
-
1447
- t.magFilter = NearestFilter;
1448
- t.minFilter = NearestFilter;
1449
-
1450
- }
1451
-
1452
- t.flipY = false;
1453
- t.wrapS = RepeatWrapping;
1454
- t.wrapT = RepeatWrapping;
1455
-
1456
- for ( let i = 0; i < texture.readyCallbacks.length; i ++ ) {
1457
-
1458
- texture.readyCallbacks[ i ]( texture );
1459
-
1460
- }
1461
-
1462
- delete texture.readyCallbacks;
1463
-
1464
- }, onProgress, onError );
1465
-
1466
- texture.readyCallbacks = [];
1467
-
1468
- textures[ fullPath ] = texture;
1469
-
1470
- return texture;
1471
-
1472
- }
1473
-
1474
- _getRotatedImage( image ) {
1475
-
1476
- const canvas = document.createElement( 'canvas' );
1477
- const context = canvas.getContext( '2d' );
1478
-
1479
- const width = image.width;
1480
- const height = image.height;
1481
-
1482
- canvas.width = width;
1483
- canvas.height = height;
1484
-
1485
- context.clearRect( 0, 0, width, height );
1486
- context.translate( width / 2.0, height / 2.0 );
1487
- context.rotate( 0.5 * Math.PI ); // 90.0 * Math.PI / 180.0
1488
- context.translate( - width / 2.0, - height / 2.0 );
1489
- context.drawImage( image, 0, 0 );
1490
-
1491
- return context.getImageData( 0, 0, width, height );
1492
-
1493
- }
1494
-
1495
- // Check if the partial image area used by the texture is transparent.
1496
- _checkImageTransparency( map, geometry, groupIndex ) {
1497
-
1498
- map.readyCallbacks.push( function ( texture ) {
1499
-
1500
- // Is there any efficient ways?
1501
- function createImageData( image ) {
1502
-
1503
- const canvas = document.createElement( 'canvas' );
1504
- canvas.width = image.width;
1505
- canvas.height = image.height;
1506
-
1507
- const context = canvas.getContext( '2d' );
1508
- context.drawImage( image, 0, 0 );
1509
-
1510
- return context.getImageData( 0, 0, canvas.width, canvas.height );
1511
-
1512
- }
1513
-
1514
- function detectImageTransparency( image, uvs, indices ) {
1515
-
1516
- const width = image.width;
1517
- const height = image.height;
1518
- const data = image.data;
1519
- const threshold = 253;
1520
-
1521
- if ( data.length / ( width * height ) !== 4 ) return false;
1522
-
1523
- for ( let i = 0; i < indices.length; i += 3 ) {
1524
-
1525
- const centerUV = { x: 0.0, y: 0.0 };
1526
-
1527
- for ( let j = 0; j < 3; j ++ ) {
1528
-
1529
- const index = indices[ i * 3 + j ];
1530
- const uv = { x: uvs[ index * 2 + 0 ], y: uvs[ index * 2 + 1 ] };
1531
-
1532
- if ( getAlphaByUv( image, uv ) < threshold ) return true;
1533
-
1534
- centerUV.x += uv.x;
1535
- centerUV.y += uv.y;
1536
-
1537
- }
1538
-
1539
- centerUV.x /= 3;
1540
- centerUV.y /= 3;
1541
-
1542
- if ( getAlphaByUv( image, centerUV ) < threshold ) return true;
1543
-
1544
- }
1545
-
1546
- return false;
1547
-
1548
- }
1549
-
1550
- /*
1551
- * This method expects
1552
- * texture.flipY = false
1553
- * texture.wrapS = RepeatWrapping
1554
- * texture.wrapT = RepeatWrapping
1555
- * TODO: more precise
1556
- */
1557
- function getAlphaByUv( image, uv ) {
1558
-
1559
- const width = image.width;
1560
- const height = image.height;
1561
-
1562
- let x = Math.round( uv.x * width ) % width;
1563
- let y = Math.round( uv.y * height ) % height;
1564
-
1565
- if ( x < 0 ) x += width;
1566
- if ( y < 0 ) y += height;
1567
-
1568
- const index = y * width + x;
1569
-
1570
- return image.data[ index * 4 + 3 ];
1571
-
1572
- }
1573
-
1574
- if ( texture.isCompressedTexture === true ) {
1575
-
1576
- if ( NON_ALPHA_CHANNEL_FORMATS.includes( texture.format ) ) {
1577
-
1578
- map.transparent = false;
1579
-
1580
- } else {
1581
-
1582
- // any other way to check transparency of CompressedTexture?
1583
- map.transparent = true;
1584
-
1585
- }
1586
-
1587
- return;
1588
-
1589
- }
1590
-
1591
- const imageData = texture.image.data !== undefined
1592
- ? texture.image
1593
- : createImageData( texture.image );
1594
-
1595
- const group = geometry.groups[ groupIndex ];
1596
-
1597
- if ( detectImageTransparency(
1598
- imageData,
1599
- geometry.attributes.uv.array,
1600
- geometry.index.array.slice( group.start, group.start + group.count ) ) ) {
1601
-
1602
- map.transparent = true;
1603
-
1604
- }
1605
-
1606
- } );
1607
-
1608
- }
1609
-
1610
- }
1611
-
1612
- //
1613
-
1614
- class AnimationBuilder {
1615
-
1616
- /**
1617
- * @param {Object} vmd - parsed VMD data
1618
- * @param {SkinnedMesh} mesh - tracks will be fitting to mesh
1619
- * @return {AnimationClip}
1620
- */
1621
- build( vmd, mesh ) {
1622
-
1623
- // combine skeletal and morph animations
1624
-
1625
- const tracks = this.buildSkeletalAnimation( vmd, mesh ).tracks;
1626
- const tracks2 = this.buildMorphAnimation( vmd, mesh ).tracks;
1627
-
1628
- for ( let i = 0, il = tracks2.length; i < il; i ++ ) {
1629
-
1630
- tracks.push( tracks2[ i ] );
1631
-
1632
- }
1633
-
1634
- return new AnimationClip( '', - 1, tracks );
1635
-
1636
- }
1637
-
1638
- /**
1639
- * @param {Object} vmd - parsed VMD data
1640
- * @param {SkinnedMesh} mesh - tracks will be fitting to mesh
1641
- * @return {AnimationClip}
1642
- */
1643
- buildSkeletalAnimation( vmd, mesh ) {
1644
-
1645
- function pushInterpolation( array, interpolation, index ) {
1646
-
1647
- array.push( interpolation[ index + 0 ] / 127 ); // x1
1648
- array.push( interpolation[ index + 8 ] / 127 ); // x2
1649
- array.push( interpolation[ index + 4 ] / 127 ); // y1
1650
- array.push( interpolation[ index + 12 ] / 127 ); // y2
1651
-
1652
- }
1653
-
1654
- const tracks = [];
1655
-
1656
- const motions = {};
1657
- const bones = mesh.skeleton.bones;
1658
- const boneNameDictionary = {};
1659
-
1660
- for ( let i = 0, il = bones.length; i < il; i ++ ) {
1661
-
1662
- boneNameDictionary[ bones[ i ].name ] = true;
1663
-
1664
- }
1665
-
1666
- for ( let i = 0; i < vmd.metadata.motionCount; i ++ ) {
1667
-
1668
- const motion = vmd.motions[ i ];
1669
- const boneName = motion.boneName;
1670
-
1671
- if ( boneNameDictionary[ boneName ] === undefined ) continue;
1672
-
1673
- motions[ boneName ] = motions[ boneName ] || [];
1674
- motions[ boneName ].push( motion );
1675
-
1676
- }
1677
-
1678
- for ( const key in motions ) {
1679
-
1680
- const array = motions[ key ];
1681
-
1682
- array.sort( function ( a, b ) {
1683
-
1684
- return a.frameNum - b.frameNum;
1685
-
1686
- } );
1687
-
1688
- const times = [];
1689
- const positions = [];
1690
- const rotations = [];
1691
- const pInterpolations = [];
1692
- const rInterpolations = [];
1693
-
1694
- const basePosition = mesh.skeleton.getBoneByName( key ).position.toArray();
1695
-
1696
- for ( let i = 0, il = array.length; i < il; i ++ ) {
1697
-
1698
- const time = array[ i ].frameNum / 30;
1699
- const position = array[ i ].position;
1700
- const rotation = array[ i ].rotation;
1701
- const interpolation = array[ i ].interpolation;
1702
-
1703
- times.push( time );
1704
-
1705
- for ( let j = 0; j < 3; j ++ ) positions.push( basePosition[ j ] + position[ j ] );
1706
- for ( let j = 0; j < 4; j ++ ) rotations.push( rotation[ j ] );
1707
- for ( let j = 0; j < 3; j ++ ) pushInterpolation( pInterpolations, interpolation, j );
1708
-
1709
- pushInterpolation( rInterpolations, interpolation, 3 );
1710
-
1711
- }
1712
-
1713
- const targetName = '.bones[' + key + ']';
1714
-
1715
- tracks.push( this._createTrack( targetName + '.position', VectorKeyframeTrack, times, positions, pInterpolations ) );
1716
- tracks.push( this._createTrack( targetName + '.quaternion', QuaternionKeyframeTrack, times, rotations, rInterpolations ) );
1717
-
1718
- }
1719
-
1720
- return new AnimationClip( '', - 1, tracks );
1721
-
1722
- }
1723
-
1724
- /**
1725
- * @param {Object} vmd - parsed VMD data
1726
- * @param {SkinnedMesh} mesh - tracks will be fitting to mesh
1727
- * @return {AnimationClip}
1728
- */
1729
- buildMorphAnimation( vmd, mesh ) {
1730
-
1731
- const tracks = [];
1732
-
1733
- const morphs = {};
1734
- const morphTargetDictionary = mesh.morphTargetDictionary;
1735
-
1736
- for ( let i = 0; i < vmd.metadata.morphCount; i ++ ) {
1737
-
1738
- const morph = vmd.morphs[ i ];
1739
- const morphName = morph.morphName;
1740
-
1741
- if ( morphTargetDictionary[ morphName ] === undefined ) continue;
1742
-
1743
- morphs[ morphName ] = morphs[ morphName ] || [];
1744
- morphs[ morphName ].push( morph );
1745
-
1746
- }
1747
-
1748
- for ( const key in morphs ) {
1749
-
1750
- const array = morphs[ key ];
1751
-
1752
- array.sort( function ( a, b ) {
1753
-
1754
- return a.frameNum - b.frameNum;
1755
-
1756
- } );
1757
-
1758
- const times = [];
1759
- const values = [];
1760
-
1761
- for ( let i = 0, il = array.length; i < il; i ++ ) {
1762
-
1763
- times.push( array[ i ].frameNum / 30 );
1764
- values.push( array[ i ].weight );
1765
-
1766
- }
1767
-
1768
- tracks.push( new NumberKeyframeTrack( '.morphTargetInfluences[' + morphTargetDictionary[ key ] + ']', times, values ) );
1769
-
1770
- }
1771
-
1772
- return new AnimationClip( '', - 1, tracks );
1773
-
1774
- }
1775
-
1776
- /**
1777
- * @param {Object} vmd - parsed VMD data
1778
- * @return {AnimationClip}
1779
- */
1780
- buildCameraAnimation( vmd ) {
1781
-
1782
- function pushVector3( array, vec ) {
1783
-
1784
- array.push( vec.x );
1785
- array.push( vec.y );
1786
- array.push( vec.z );
1787
-
1788
- }
1789
-
1790
- function pushQuaternion( array, q ) {
1791
-
1792
- array.push( q.x );
1793
- array.push( q.y );
1794
- array.push( q.z );
1795
- array.push( q.w );
1796
-
1797
- }
1798
-
1799
- function pushInterpolation( array, interpolation, index ) {
1800
-
1801
- array.push( interpolation[ index * 4 + 0 ] / 127 ); // x1
1802
- array.push( interpolation[ index * 4 + 1 ] / 127 ); // x2
1803
- array.push( interpolation[ index * 4 + 2 ] / 127 ); // y1
1804
- array.push( interpolation[ index * 4 + 3 ] / 127 ); // y2
1805
-
1806
- }
1807
-
1808
- const cameras = vmd.cameras === undefined ? [] : vmd.cameras.slice();
1809
-
1810
- cameras.sort( function ( a, b ) {
1811
-
1812
- return a.frameNum - b.frameNum;
1813
-
1814
- } );
1815
-
1816
- const times = [];
1817
- const centers = [];
1818
- const quaternions = [];
1819
- const positions = [];
1820
- const fovs = [];
1821
-
1822
- const cInterpolations = [];
1823
- const qInterpolations = [];
1824
- const pInterpolations = [];
1825
- const fInterpolations = [];
1826
-
1827
- const quaternion = new Quaternion();
1828
- const euler = new Euler();
1829
- const position = new Vector3();
1830
- const center = new Vector3();
1831
-
1832
- for ( let i = 0, il = cameras.length; i < il; i ++ ) {
1833
-
1834
- const motion = cameras[ i ];
1835
-
1836
- const time = motion.frameNum / 30;
1837
- const pos = motion.position;
1838
- const rot = motion.rotation;
1839
- const distance = motion.distance;
1840
- const fov = motion.fov;
1841
- const interpolation = motion.interpolation;
1842
-
1843
- times.push( time );
1844
-
1845
- position.set( 0, 0, - distance );
1846
- center.set( pos[ 0 ], pos[ 1 ], pos[ 2 ] );
1847
-
1848
- euler.set( - rot[ 0 ], - rot[ 1 ], - rot[ 2 ] );
1849
- quaternion.setFromEuler( euler );
1850
-
1851
- position.add( center );
1852
- position.applyQuaternion( quaternion );
1853
-
1854
- pushVector3( centers, center );
1855
- pushQuaternion( quaternions, quaternion );
1856
- pushVector3( positions, position );
1857
-
1858
- fovs.push( fov );
1859
-
1860
- for ( let j = 0; j < 3; j ++ ) {
1861
-
1862
- pushInterpolation( cInterpolations, interpolation, j );
1863
-
1864
- }
1865
-
1866
- pushInterpolation( qInterpolations, interpolation, 3 );
1867
-
1868
- // use the same parameter for x, y, z axis.
1869
- for ( let j = 0; j < 3; j ++ ) {
1870
-
1871
- pushInterpolation( pInterpolations, interpolation, 4 );
1872
-
1873
- }
1874
-
1875
- pushInterpolation( fInterpolations, interpolation, 5 );
1876
-
1877
- }
1878
-
1879
- const tracks = [];
1880
-
1881
- // I expect an object whose name 'target' exists under THREE.Camera
1882
- tracks.push( this._createTrack( 'target.position', VectorKeyframeTrack, times, centers, cInterpolations ) );
1883
-
1884
- tracks.push( this._createTrack( '.quaternion', QuaternionKeyframeTrack, times, quaternions, qInterpolations ) );
1885
- tracks.push( this._createTrack( '.position', VectorKeyframeTrack, times, positions, pInterpolations ) );
1886
- tracks.push( this._createTrack( '.fov', NumberKeyframeTrack, times, fovs, fInterpolations ) );
1887
-
1888
- return new AnimationClip( '', - 1, tracks );
1889
-
1890
- }
1891
-
1892
- // private method
1893
-
1894
- _createTrack( node, typedKeyframeTrack, times, values, interpolations ) {
1895
-
1896
- /*
1897
- * optimizes here not to let KeyframeTrackPrototype optimize
1898
- * because KeyframeTrackPrototype optimizes times and values but
1899
- * doesn't optimize interpolations.
1900
- */
1901
- if ( times.length > 2 ) {
1902
-
1903
- times = times.slice();
1904
- values = values.slice();
1905
- interpolations = interpolations.slice();
1906
-
1907
- const stride = values.length / times.length;
1908
- const interpolateStride = interpolations.length / times.length;
1909
-
1910
- let index = 1;
1911
-
1912
- for ( let aheadIndex = 2, endIndex = times.length; aheadIndex < endIndex; aheadIndex ++ ) {
1913
-
1914
- for ( let i = 0; i < stride; i ++ ) {
1915
-
1916
- if ( values[ index * stride + i ] !== values[ ( index - 1 ) * stride + i ] ||
1917
- values[ index * stride + i ] !== values[ aheadIndex * stride + i ] ) {
1918
-
1919
- index ++;
1920
- break;
1921
-
1922
- }
1923
-
1924
- }
1925
-
1926
- if ( aheadIndex > index ) {
1927
-
1928
- times[ index ] = times[ aheadIndex ];
1929
-
1930
- for ( let i = 0; i < stride; i ++ ) {
1931
-
1932
- values[ index * stride + i ] = values[ aheadIndex * stride + i ];
1933
-
1934
- }
1935
-
1936
- for ( let i = 0; i < interpolateStride; i ++ ) {
1937
-
1938
- interpolations[ index * interpolateStride + i ] = interpolations[ aheadIndex * interpolateStride + i ];
1939
-
1940
- }
1941
-
1942
- }
1943
-
1944
- }
1945
-
1946
- times.length = index + 1;
1947
- values.length = ( index + 1 ) * stride;
1948
- interpolations.length = ( index + 1 ) * interpolateStride;
1949
-
1950
- }
1951
-
1952
- const track = new typedKeyframeTrack( node, times, values );
1953
-
1954
- track.createInterpolant = function InterpolantFactoryMethodCubicBezier( result ) {
1955
-
1956
- return new CubicBezierInterpolation( this.times, this.values, this.getValueSize(), result, new Float32Array( interpolations ) );
1957
-
1958
- };
1959
-
1960
- return track;
1961
-
1962
- }
1963
-
1964
- }
1965
-
1966
- // interpolation
1967
-
1968
- class CubicBezierInterpolation extends Interpolant {
1969
-
1970
- constructor( parameterPositions, sampleValues, sampleSize, resultBuffer, params ) {
1971
-
1972
- super( parameterPositions, sampleValues, sampleSize, resultBuffer );
1973
-
1974
- this.interpolationParams = params;
1975
-
1976
- }
1977
-
1978
- interpolate_( i1, t0, t, t1 ) {
1979
-
1980
- const result = this.resultBuffer;
1981
- const values = this.sampleValues;
1982
- const stride = this.valueSize;
1983
- const params = this.interpolationParams;
1984
-
1985
- const offset1 = i1 * stride;
1986
- const offset0 = offset1 - stride;
1987
-
1988
- // No interpolation if next key frame is in one frame in 30fps.
1989
- // This is from MMD animation spec.
1990
- // '1.5' is for precision loss. times are Float32 in Three.js Animation system.
1991
- const weight1 = ( ( t1 - t0 ) < 1 / 30 * 1.5 ) ? 0.0 : ( t - t0 ) / ( t1 - t0 );
1992
-
1993
- if ( stride === 4 ) { // Quaternion
1994
-
1995
- const x1 = params[ i1 * 4 + 0 ];
1996
- const x2 = params[ i1 * 4 + 1 ];
1997
- const y1 = params[ i1 * 4 + 2 ];
1998
- const y2 = params[ i1 * 4 + 3 ];
1999
-
2000
- const ratio = this._calculate( x1, x2, y1, y2, weight1 );
2001
-
2002
- Quaternion.slerpFlat( result, 0, values, offset0, values, offset1, ratio );
2003
-
2004
- } else if ( stride === 3 ) { // Vector3
2005
-
2006
- for ( let i = 0; i !== stride; ++ i ) {
2007
-
2008
- const x1 = params[ i1 * 12 + i * 4 + 0 ];
2009
- const x2 = params[ i1 * 12 + i * 4 + 1 ];
2010
- const y1 = params[ i1 * 12 + i * 4 + 2 ];
2011
- const y2 = params[ i1 * 12 + i * 4 + 3 ];
2012
-
2013
- const ratio = this._calculate( x1, x2, y1, y2, weight1 );
2014
-
2015
- result[ i ] = values[ offset0 + i ] * ( 1 - ratio ) + values[ offset1 + i ] * ratio;
2016
-
2017
- }
2018
-
2019
- } else { // Number
2020
-
2021
- const x1 = params[ i1 * 4 + 0 ];
2022
- const x2 = params[ i1 * 4 + 1 ];
2023
- const y1 = params[ i1 * 4 + 2 ];
2024
- const y2 = params[ i1 * 4 + 3 ];
2025
-
2026
- const ratio = this._calculate( x1, x2, y1, y2, weight1 );
2027
-
2028
- result[ 0 ] = values[ offset0 ] * ( 1 - ratio ) + values[ offset1 ] * ratio;
2029
-
2030
- }
2031
-
2032
- return result;
2033
-
2034
- }
2035
-
2036
- _calculate( x1, x2, y1, y2, x ) {
2037
-
2038
- /*
2039
- * Cubic Bezier curves
2040
- * https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Cubic_B.C3.A9zier_curves
2041
- *
2042
- * B(t) = ( 1 - t ) ^ 3 * P0
2043
- * + 3 * ( 1 - t ) ^ 2 * t * P1
2044
- * + 3 * ( 1 - t ) * t^2 * P2
2045
- * + t ^ 3 * P3
2046
- * ( 0 <= t <= 1 )
2047
- *
2048
- * MMD uses Cubic Bezier curves for bone and camera animation interpolation.
2049
- * http://d.hatena.ne.jp/edvakf/20111016/1318716097
2050
- *
2051
- * x = ( 1 - t ) ^ 3 * x0
2052
- * + 3 * ( 1 - t ) ^ 2 * t * x1
2053
- * + 3 * ( 1 - t ) * t^2 * x2
2054
- * + t ^ 3 * x3
2055
- * y = ( 1 - t ) ^ 3 * y0
2056
- * + 3 * ( 1 - t ) ^ 2 * t * y1
2057
- * + 3 * ( 1 - t ) * t^2 * y2
2058
- * + t ^ 3 * y3
2059
- * ( x0 = 0, y0 = 0 )
2060
- * ( x3 = 1, y3 = 1 )
2061
- * ( 0 <= t, x1, x2, y1, y2 <= 1 )
2062
- *
2063
- * Here solves this equation with Bisection method,
2064
- * https://en.wikipedia.org/wiki/Bisection_method
2065
- * gets t, and then calculate y.
2066
- *
2067
- * f(t) = 3 * ( 1 - t ) ^ 2 * t * x1
2068
- * + 3 * ( 1 - t ) * t^2 * x2
2069
- * + t ^ 3 - x = 0
2070
- *
2071
- * (Another option: Newton's method
2072
- * https://en.wikipedia.org/wiki/Newton%27s_method)
2073
- */
2074
-
2075
- let c = 0.5;
2076
- let t = c;
2077
- let s = 1.0 - t;
2078
- const loop = 15;
2079
- const eps = 1e-5;
2080
- const math = Math;
2081
-
2082
- let sst3, stt3, ttt;
2083
-
2084
- for ( let i = 0; i < loop; i ++ ) {
2085
-
2086
- sst3 = 3.0 * s * s * t;
2087
- stt3 = 3.0 * s * t * t;
2088
- ttt = t * t * t;
2089
-
2090
- const ft = ( sst3 * x1 ) + ( stt3 * x2 ) + ( ttt ) - x;
2091
-
2092
- if ( math.abs( ft ) < eps ) break;
2093
-
2094
- c /= 2.0;
2095
-
2096
- t += ( ft < 0 ) ? c : - c;
2097
- s = 1.0 - t;
2098
-
2099
- }
2100
-
2101
- return ( sst3 * y1 ) + ( stt3 * y2 ) + ttt;
2102
-
2103
- }
2104
-
2105
- }
2106
-
2107
- class MMDToonMaterial extends ShaderMaterial {
2108
-
2109
- constructor( parameters ) {
2110
-
2111
- super();
2112
-
2113
- this.isMMDToonMaterial = true;
2114
-
2115
- this.type = 'MMDToonMaterial';
2116
-
2117
- this._matcapCombine = AddOperation;
2118
- this.emissiveIntensity = 1.0;
2119
- this.normalMapType = TangentSpaceNormalMap;
2120
-
2121
- this.combine = MultiplyOperation;
2122
-
2123
- this.wireframeLinecap = 'round';
2124
- this.wireframeLinejoin = 'round';
2125
-
2126
- this.flatShading = false;
2127
-
2128
- this.lights = true;
2129
-
2130
- this.vertexShader = MMDToonShader.vertexShader;
2131
- this.fragmentShader = MMDToonShader.fragmentShader;
2132
-
2133
- this.defines = Object.assign( {}, MMDToonShader.defines );
2134
- Object.defineProperty( this, 'matcapCombine', {
2135
-
2136
- get: function () {
2137
-
2138
- return this._matcapCombine;
2139
-
2140
- },
2141
-
2142
- set: function ( value ) {
2143
-
2144
- this._matcapCombine = value;
2145
-
2146
- switch ( value ) {
2147
-
2148
- case MultiplyOperation:
2149
- this.defines.MATCAP_BLENDING_MULTIPLY = true;
2150
- delete this.defines.MATCAP_BLENDING_ADD;
2151
- break;
2152
-
2153
- default:
2154
- case AddOperation:
2155
- this.defines.MATCAP_BLENDING_ADD = true;
2156
- delete this.defines.MATCAP_BLENDING_MULTIPLY;
2157
- break;
2158
-
2159
- }
2160
-
2161
- },
2162
-
2163
- } );
2164
-
2165
- this.uniforms = UniformsUtils.clone( MMDToonShader.uniforms );
2166
-
2167
- // merged from MeshToon/Phong/MatcapMaterial
2168
- const exposePropertyNames = [
2169
- 'specular',
2170
- 'opacity',
2171
- 'diffuse',
2172
-
2173
- 'map',
2174
- 'matcap',
2175
- 'gradientMap',
2176
-
2177
- 'lightMap',
2178
- 'lightMapIntensity',
2179
-
2180
- 'aoMap',
2181
- 'aoMapIntensity',
2182
-
2183
- 'emissive',
2184
- 'emissiveMap',
2185
-
2186
- 'bumpMap',
2187
- 'bumpScale',
2188
-
2189
- 'normalMap',
2190
- 'normalScale',
2191
-
2192
- 'displacemantBias',
2193
- 'displacemantMap',
2194
- 'displacemantScale',
2195
-
2196
- 'specularMap',
2197
-
2198
- 'alphaMap',
2199
-
2200
- 'reflectivity',
2201
- 'refractionRatio',
2202
- ];
2203
- for ( const propertyName of exposePropertyNames ) {
2204
-
2205
- Object.defineProperty( this, propertyName, {
2206
-
2207
- get: function () {
2208
-
2209
- return this.uniforms[ propertyName ].value;
2210
-
2211
- },
2212
-
2213
- set: function ( value ) {
2214
-
2215
- this.uniforms[ propertyName ].value = value;
2216
-
2217
- },
2218
-
2219
- } );
2220
-
2221
- }
2222
-
2223
- // Special path for shininess to handle zero shininess properly
2224
- this._shininess = 30;
2225
- Object.defineProperty( this, 'shininess', {
2226
-
2227
- get: function () {
2228
-
2229
- return this._shininess;
2230
-
2231
- },
2232
-
2233
- set: function ( value ) {
2234
-
2235
- this._shininess = value;
2236
- this.uniforms.shininess.value = Math.max( this._shininess, 1e-4 ); // To prevent pow( 0.0, 0.0 )
2237
-
2238
- },
2239
-
2240
- } );
2241
-
2242
- Object.defineProperty(
2243
- this,
2244
- 'color',
2245
- Object.getOwnPropertyDescriptor( this, 'diffuse' )
2246
- );
2247
-
2248
- this.setValues( parameters );
2249
-
2250
- }
2251
-
2252
- copy( source ) {
2253
-
2254
- super.copy( source );
2255
-
2256
- this.matcapCombine = source.matcapCombine;
2257
- this.emissiveIntensity = source.emissiveIntensity;
2258
- this.normalMapType = source.normalMapType;
2259
-
2260
- this.combine = source.combine;
2261
-
2262
- this.wireframeLinecap = source.wireframeLinecap;
2263
- this.wireframeLinejoin = source.wireframeLinejoin;
2264
-
2265
- this.flatShading = source.flatShading;
2266
-
2267
- return this;
2268
-
2269
- }
2270
-
2271
- }
2272
-
2273
- export { MMDLoader };
1
+ import {
2
+ AddOperation,
3
+ AnimationClip,
4
+ Bone,
5
+ BufferGeometry,
6
+ Color,
7
+ CustomBlending,
8
+ TangentSpaceNormalMap,
9
+ DoubleSide,
10
+ DstAlphaFactor,
11
+ Euler,
12
+ FileLoader,
13
+ Float32BufferAttribute,
14
+ FrontSide,
15
+ Interpolant,
16
+ Loader,
17
+ LoaderUtils,
18
+ UniformsUtils,
19
+ ShaderMaterial,
20
+ MultiplyOperation,
21
+ NearestFilter,
22
+ NumberKeyframeTrack,
23
+ OneMinusSrcAlphaFactor,
24
+ Quaternion,
25
+ QuaternionKeyframeTrack,
26
+ RepeatWrapping,
27
+ Skeleton,
28
+ SkinnedMesh,
29
+ SrcAlphaFactor,
30
+ SRGBColorSpace,
31
+ TextureLoader,
32
+ Uint16BufferAttribute,
33
+ Vector3,
34
+ VectorKeyframeTrack,
35
+ RGB_S3TC_DXT1_Format,
36
+ RGB_PVRTC_4BPPV1_Format,
37
+ RGB_PVRTC_2BPPV1_Format,
38
+ RGB_ETC1_Format,
39
+ RGB_ETC2_Format
40
+ } from 'three';
41
+ import { MMDToonShader } from '../shaders/MMDToonShader.js';
42
+ import { TGALoader } from '../loaders/TGALoader.js';
43
+ import { MMDParser } from '../libs/mmdparser.module.js';
44
+
45
+ /**
46
+ * Dependencies
47
+ * - mmd-parser https://github.com/takahirox/mmd-parser
48
+ * - TGALoader
49
+ * - OutlineEffect
50
+ *
51
+ * MMDLoader creates Three.js Objects from MMD resources as
52
+ * PMD, PMX, VMD, and VPD files.
53
+ *
54
+ * PMD/PMX is a model data format, VMD is a motion data format
55
+ * VPD is a posing data format used in MMD(Miku Miku Dance).
56
+ *
57
+ * MMD official site
58
+ * - https://sites.google.com/view/evpvp/
59
+ *
60
+ * PMD, VMD format (in Japanese)
61
+ * - http://blog.goo.ne.jp/torisu_tetosuki/e/209ad341d3ece2b1b4df24abf619d6e4
62
+ *
63
+ * PMX format
64
+ * - https://gist.github.com/felixjones/f8a06bd48f9da9a4539f
65
+ *
66
+ * TODO
67
+ * - light motion in vmd support.
68
+ * - SDEF support.
69
+ * - uv/material/bone morphing support.
70
+ * - more precise grant skinning support.
71
+ * - shadow support.
72
+ */
73
+
74
+ /**
75
+ * @param {THREE.LoadingManager} manager
76
+ */
77
+ class MMDLoader extends Loader {
78
+
79
+ constructor( manager ) {
80
+
81
+ super( manager );
82
+
83
+ this.loader = new FileLoader( this.manager );
84
+
85
+ this.parser = null; // lazy generation
86
+ this.meshBuilder = new MeshBuilder( this.manager );
87
+ this.animationBuilder = new AnimationBuilder();
88
+
89
+ }
90
+
91
+ /**
92
+ * @param {string} animationPath
93
+ * @return {MMDLoader}
94
+ */
95
+ setAnimationPath( animationPath ) {
96
+
97
+ this.animationPath = animationPath;
98
+ return this;
99
+
100
+ }
101
+
102
+ // Load MMD assets as Three.js Object
103
+
104
+ /**
105
+ * Loads Model file (.pmd or .pmx) as a SkinnedMesh.
106
+ *
107
+ * @param {string} url - url to Model(.pmd or .pmx) file
108
+ * @param {function} onLoad
109
+ * @param {function} onProgress
110
+ * @param {function} onError
111
+ */
112
+ load( url, onLoad, onProgress, onError ) {
113
+
114
+ const builder = this.meshBuilder.setCrossOrigin( this.crossOrigin );
115
+
116
+ // resource path
117
+
118
+ let resourcePath;
119
+
120
+ if ( this.resourcePath !== '' ) {
121
+
122
+ resourcePath = this.resourcePath;
123
+
124
+ } else if ( this.path !== '' ) {
125
+
126
+ resourcePath = this.path;
127
+
128
+ } else {
129
+
130
+ resourcePath = LoaderUtils.extractUrlBase( url );
131
+
132
+ }
133
+
134
+ const modelExtension = this._extractExtension( url ).toLowerCase();
135
+
136
+ // Should I detect by seeing header?
137
+ if ( modelExtension !== 'pmd' && modelExtension !== 'pmx' ) {
138
+
139
+ if ( onError ) onError( new Error( 'THREE.MMDLoader: Unknown model file extension .' + modelExtension + '.' ) );
140
+
141
+ return;
142
+
143
+ }
144
+
145
+ this[ modelExtension === 'pmd' ? 'loadPMD' : 'loadPMX' ]( url, function ( data ) {
146
+
147
+ onLoad( builder.build( data, resourcePath, onProgress, onError ) );
148
+
149
+ }, onProgress, onError );
150
+
151
+ }
152
+
153
+ /**
154
+ * Loads Motion file(s) (.vmd) as a AnimationClip.
155
+ * If two or more files are specified, they'll be merged.
156
+ *
157
+ * @param {string|Array<string>} url - url(s) to animation(.vmd) file(s)
158
+ * @param {SkinnedMesh|THREE.Camera} object - tracks will be fitting to this object
159
+ * @param {function} onLoad
160
+ * @param {function} onProgress
161
+ * @param {function} onError
162
+ */
163
+ loadAnimation( url, object, onLoad, onProgress, onError ) {
164
+
165
+ const builder = this.animationBuilder;
166
+
167
+ this.loadVMD( url, function ( vmd ) {
168
+
169
+ onLoad( object.isCamera
170
+ ? builder.buildCameraAnimation( vmd )
171
+ : builder.build( vmd, object ) );
172
+
173
+ }, onProgress, onError );
174
+
175
+ }
176
+
177
+ /**
178
+ * Loads mode file and motion file(s) as an object containing
179
+ * a SkinnedMesh and a AnimationClip.
180
+ * Tracks of AnimationClip are fitting to the model.
181
+ *
182
+ * @param {string} modelUrl - url to Model(.pmd or .pmx) file
183
+ * @param {string|Array{string}} vmdUrl - url(s) to animation(.vmd) file
184
+ * @param {function} onLoad
185
+ * @param {function} onProgress
186
+ * @param {function} onError
187
+ */
188
+ loadWithAnimation( modelUrl, vmdUrl, onLoad, onProgress, onError ) {
189
+
190
+ const scope = this;
191
+
192
+ this.load( modelUrl, function ( mesh ) {
193
+
194
+ scope.loadAnimation( vmdUrl, mesh, function ( animation ) {
195
+
196
+ onLoad( {
197
+ mesh: mesh,
198
+ animation: animation
199
+ } );
200
+
201
+ }, onProgress, onError );
202
+
203
+ }, onProgress, onError );
204
+
205
+ }
206
+
207
+ // Load MMD assets as Object data parsed by MMDParser
208
+
209
+ /**
210
+ * Loads .pmd file as an Object.
211
+ *
212
+ * @param {string} url - url to .pmd file
213
+ * @param {function} onLoad
214
+ * @param {function} onProgress
215
+ * @param {function} onError
216
+ */
217
+ loadPMD( url, onLoad, onProgress, onError ) {
218
+
219
+ const parser = this._getParser();
220
+
221
+ this.loader
222
+ .setMimeType( undefined )
223
+ .setPath( this.path )
224
+ .setResponseType( 'arraybuffer' )
225
+ .setRequestHeader( this.requestHeader )
226
+ .setWithCredentials( this.withCredentials )
227
+ .load( url, function ( buffer ) {
228
+
229
+ try {
230
+
231
+ onLoad( parser.parsePmd( buffer, true ) );
232
+
233
+ } catch ( e ) {
234
+
235
+ if ( onError ) onError( e );
236
+
237
+ }
238
+
239
+ }, onProgress, onError );
240
+
241
+ }
242
+
243
+ /**
244
+ * Loads .pmx file as an Object.
245
+ *
246
+ * @param {string} url - url to .pmx file
247
+ * @param {function} onLoad
248
+ * @param {function} onProgress
249
+ * @param {function} onError
250
+ */
251
+ loadPMX( url, onLoad, onProgress, onError ) {
252
+
253
+ const parser = this._getParser();
254
+
255
+ this.loader
256
+ .setMimeType( undefined )
257
+ .setPath( this.path )
258
+ .setResponseType( 'arraybuffer' )
259
+ .setRequestHeader( this.requestHeader )
260
+ .setWithCredentials( this.withCredentials )
261
+ .load( url, function ( buffer ) {
262
+
263
+ try {
264
+
265
+ onLoad( parser.parsePmx( buffer, true ) );
266
+
267
+ } catch ( e ) {
268
+
269
+ if ( onError ) onError( e );
270
+
271
+ }
272
+
273
+ }, onProgress, onError );
274
+
275
+ }
276
+
277
+ /**
278
+ * Loads .vmd file as an Object. If two or more files are specified
279
+ * they'll be merged.
280
+ *
281
+ * @param {string|Array<string>} url - url(s) to .vmd file(s)
282
+ * @param {function} onLoad
283
+ * @param {function} onProgress
284
+ * @param {function} onError
285
+ */
286
+ loadVMD( url, onLoad, onProgress, onError ) {
287
+
288
+ const urls = Array.isArray( url ) ? url : [ url ];
289
+
290
+ const vmds = [];
291
+ const vmdNum = urls.length;
292
+
293
+ const parser = this._getParser();
294
+
295
+ this.loader
296
+ .setMimeType( undefined )
297
+ .setPath( this.animationPath )
298
+ .setResponseType( 'arraybuffer' )
299
+ .setRequestHeader( this.requestHeader )
300
+ .setWithCredentials( this.withCredentials );
301
+
302
+ for ( let i = 0, il = urls.length; i < il; i ++ ) {
303
+
304
+ this.loader.load( urls[ i ], function ( buffer ) {
305
+
306
+ try {
307
+
308
+ vmds.push( parser.parseVmd( buffer, true ) );
309
+
310
+ if ( vmds.length === vmdNum ) onLoad( parser.mergeVmds( vmds ) );
311
+
312
+ } catch ( e ) {
313
+
314
+ if ( onError ) onError( e );
315
+
316
+ }
317
+
318
+ }, onProgress, onError );
319
+
320
+ }
321
+
322
+ }
323
+
324
+ /**
325
+ * Loads .vpd file as an Object.
326
+ *
327
+ * @param {string} url - url to .vpd file
328
+ * @param {boolean} isUnicode
329
+ * @param {function} onLoad
330
+ * @param {function} onProgress
331
+ * @param {function} onError
332
+ */
333
+ loadVPD( url, isUnicode, onLoad, onProgress, onError ) {
334
+
335
+ const parser = this._getParser();
336
+
337
+ this.loader
338
+ .setMimeType( isUnicode ? undefined : 'text/plain; charset=shift_jis' )
339
+ .setPath( this.animationPath )
340
+ .setResponseType( 'text' )
341
+ .setRequestHeader( this.requestHeader )
342
+ .setWithCredentials( this.withCredentials )
343
+ .load( url, function ( text ) {
344
+
345
+ try {
346
+
347
+ onLoad( parser.parseVpd( text, true ) );
348
+
349
+ } catch ( e ) {
350
+
351
+ if ( onError ) onError( e );
352
+
353
+ }
354
+
355
+ }, onProgress, onError );
356
+
357
+ }
358
+
359
+ // private methods
360
+
361
+ _extractExtension( url ) {
362
+
363
+ const index = url.lastIndexOf( '.' );
364
+ return index < 0 ? '' : url.slice( index + 1 );
365
+
366
+ }
367
+
368
+ _getParser() {
369
+
370
+ if ( this.parser === null ) {
371
+
372
+ this.parser = new MMDParser.Parser();
373
+
374
+ }
375
+
376
+ return this.parser;
377
+
378
+ }
379
+
380
+ }
381
+
382
+ // Utilities
383
+
384
+ /*
385
+ * base64 encoded defalut toon textures toon00.bmp - toon10.bmp.
386
+ * We don't need to request external toon image files.
387
+ */
388
+ const DEFAULT_TOON_TEXTURES = [
389
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=',
390
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAN0lEQVRYR+3WQREAMBACsZ5/bWiiMvgEBTt5cW37hjsBBAgQIECAwFwgyfYPCCBAgAABAgTWAh8aBHZBl14e8wAAAABJRU5ErkJggg==',
391
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAOUlEQVRYR+3WMREAMAwDsYY/yoDI7MLwIiP40+RJklfcCCBAgAABAgTqArfb/QMCCBAgQIAAgbbAB3z/e0F3js2cAAAAAElFTkSuQmCC',
392
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAN0lEQVRYR+3WQREAMBACsZ5/B5ilMvgEBTt5cW37hjsBBAgQIECAwFwgyfYPCCBAgAABAgTWAh81dWyx0gFwKAAAAABJRU5ErkJggg==',
393
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAOklEQVRYR+3WoREAMAwDsWb/UQtCy9wxTOQJ/oQ8SXKKGwEECBAgQIBAXeDt7f4BAQQIECBAgEBb4AOz8Hzx7WLY4wAAAABJRU5ErkJggg==',
394
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABPUlEQVRYR+1XwW7CMAy1+f9fZOMysSEOEweEOPRNdm3HbdOyIhAcklPrOs/PLy9RygBALxzcCDQFmgJNgaZAU6Ap0BR4PwX8gsRMVLssMRH5HcpzJEaWL7EVg9F1IHRlyqQohgVr4FGUlUcMJSjcUlDw0zvjeun70cLWmneoyf7NgBTQSniBTQQSuJAZsOnnaczjIMb5hCiuHKxokCrJfVnrctyZL0PkJAJe1HMil4nxeyi3Ypfn1kX51jpPvo/JeCNC4PhVdHdJw2XjBR8brF8PEIhNVn12AgP7uHsTBguBn53MUZCqv7Lp07Pn5k1Ro+uWmUNn7D+M57rtk7aG0Vo73xyF/fbFf0bPJjDXngnGocDTdFhygZjwUQrMNrDcmZlQT50VJ/g/UwNyHpu778+yW+/ksOz/BFo54P4AsUXMfRq7XWsAAAAASUVORK5CYII=',
395
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACMElEQVRYR+2Xv4pTQRTGf2dubhLdICiii2KnYKHVolhauKWPoGAnNr6BD6CvIVaihYuI2i1ia0BY0MZGRHQXjZj/mSPnnskfNWiWZUlzJ5k7M2cm833nO5Mziej2DWWJRUoCpQKlAntSQCqgw39/iUWAGmh37jrRnVsKlgpiqmkoGVABA7E57fvY+pJDdgKqF6HzFCSADkDq+F6AHABtQ+UMVE5D7zXod7fFNhTEckTbj5XQgHzNN+5tQvc5NG7C6BNkp6D3EmpXHDR+dQAjFLchW3VS9rlw3JBh+B7ys5Cf9z0GW1C/7P32AyBAOAz1q4jGliIH3YPuBnSfQX4OGreTIgEYQb/pBDtPnEQ4CivXYPAWBk13oHrB54yA9QuSn2H4AcKRpEILDt0BUzj+RLR1V5EqjD66NPRBVpLcQwjHoHYJOhsQv6U4mnzmrIXJCFr4LDwm/xBUoboG9XX4cc9VKdYoSA2yk5NQLJaKDUjTBoveG3Z2TElTxwjNK4M3LEZgUdDdruvcXzKBpStgp2NPiWi3ks9ZXxIoFVi+AvHLdc9TqtjL3/aYjpPlrzOcEnK62Szhimdd7xX232zFDTgtxezOu3WNMRLjiKgjtOhHVMd1loynVHvOgjuIIJMaELEqhJAV/RCSLbWTcfPFakFgFlALTRRvx+ok6Hlp/Q+v3fmx90bMyUzaEAhmM3KvHlXTL5DxnbGf/1M8RNNACLL5MNtPxP/mypJAqcDSFfgFhpYqWUzhTEAAAAAASUVORK5CYII=',
396
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=',
397
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=',
398
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=',
399
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII='
400
+ ];
401
+
402
+ const NON_ALPHA_CHANNEL_FORMATS = [
403
+ RGB_S3TC_DXT1_Format,
404
+ RGB_PVRTC_4BPPV1_Format,
405
+ RGB_PVRTC_2BPPV1_Format,
406
+ RGB_ETC1_Format,
407
+ RGB_ETC2_Format
408
+ ];
409
+
410
+ // Builders. They build Three.js object from Object data parsed by MMDParser.
411
+
412
+ /**
413
+ * @param {THREE.LoadingManager} manager
414
+ */
415
+ class MeshBuilder {
416
+
417
+ constructor( manager ) {
418
+
419
+ this.crossOrigin = 'anonymous';
420
+ this.geometryBuilder = new GeometryBuilder();
421
+ this.materialBuilder = new MaterialBuilder( manager );
422
+
423
+ }
424
+
425
+ /**
426
+ * @param {string} crossOrigin
427
+ * @return {MeshBuilder}
428
+ */
429
+ setCrossOrigin( crossOrigin ) {
430
+
431
+ this.crossOrigin = crossOrigin;
432
+ return this;
433
+
434
+ }
435
+
436
+ /**
437
+ * @param {Object} data - parsed PMD/PMX data
438
+ * @param {string} resourcePath
439
+ * @param {function} onProgress
440
+ * @param {function} onError
441
+ * @return {SkinnedMesh}
442
+ */
443
+ build( data, resourcePath, onProgress, onError ) {
444
+
445
+ const geometry = this.geometryBuilder.build( data );
446
+ const material = this.materialBuilder
447
+ .setCrossOrigin( this.crossOrigin )
448
+ .setResourcePath( resourcePath )
449
+ .build( data, geometry, onProgress, onError );
450
+
451
+ const mesh = new SkinnedMesh( geometry, material );
452
+
453
+ const skeleton = new Skeleton( initBones( mesh ) );
454
+ mesh.bind( skeleton );
455
+
456
+ // console.log( mesh ); // for console debug
457
+
458
+ return mesh;
459
+
460
+ }
461
+
462
+ }
463
+
464
+ // TODO: Try to remove this function
465
+
466
+ function initBones( mesh ) {
467
+
468
+ const geometry = mesh.geometry;
469
+
470
+ const bones = [];
471
+
472
+ if ( geometry && geometry.bones !== undefined ) {
473
+
474
+ // first, create array of 'Bone' objects from geometry data
475
+
476
+ for ( let i = 0, il = geometry.bones.length; i < il; i ++ ) {
477
+
478
+ const gbone = geometry.bones[ i ];
479
+
480
+ // create new 'Bone' object
481
+
482
+ const bone = new Bone();
483
+ bones.push( bone );
484
+
485
+ // apply values
486
+
487
+ bone.name = gbone.name;
488
+ bone.position.fromArray( gbone.pos );
489
+ bone.quaternion.fromArray( gbone.rotq );
490
+ if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl );
491
+
492
+ }
493
+
494
+ // second, create bone hierarchy
495
+
496
+ for ( let i = 0, il = geometry.bones.length; i < il; i ++ ) {
497
+
498
+ const gbone = geometry.bones[ i ];
499
+
500
+ if ( ( gbone.parent !== - 1 ) && ( gbone.parent !== null ) && ( bones[ gbone.parent ] !== undefined ) ) {
501
+
502
+ // subsequent bones in the hierarchy
503
+
504
+ bones[ gbone.parent ].add( bones[ i ] );
505
+
506
+ } else {
507
+
508
+ // topmost bone, immediate child of the skinned mesh
509
+
510
+ mesh.add( bones[ i ] );
511
+
512
+ }
513
+
514
+ }
515
+
516
+ }
517
+
518
+ // now the bones are part of the scene graph and children of the skinned mesh.
519
+ // let's update the corresponding matrices
520
+
521
+ mesh.updateMatrixWorld( true );
522
+
523
+ return bones;
524
+
525
+ }
526
+
527
+ //
528
+
529
+ class GeometryBuilder {
530
+
531
+ /**
532
+ * @param {Object} data - parsed PMD/PMX data
533
+ * @return {BufferGeometry}
534
+ */
535
+ build( data ) {
536
+
537
+ // for geometry
538
+ const positions = [];
539
+ const uvs = [];
540
+ const normals = [];
541
+
542
+ const indices = [];
543
+
544
+ const groups = [];
545
+
546
+ const bones = [];
547
+ const skinIndices = [];
548
+ const skinWeights = [];
549
+
550
+ const morphTargets = [];
551
+ const morphPositions = [];
552
+
553
+ const iks = [];
554
+ const grants = [];
555
+
556
+ const rigidBodies = [];
557
+ const constraints = [];
558
+
559
+ // for work
560
+ let offset = 0;
561
+ const boneTypeTable = {};
562
+
563
+ // positions, normals, uvs, skinIndices, skinWeights
564
+
565
+ for ( let i = 0; i < data.metadata.vertexCount; i ++ ) {
566
+
567
+ const v = data.vertices[ i ];
568
+
569
+ for ( let j = 0, jl = v.position.length; j < jl; j ++ ) {
570
+
571
+ positions.push( v.position[ j ] );
572
+
573
+ }
574
+
575
+ for ( let j = 0, jl = v.normal.length; j < jl; j ++ ) {
576
+
577
+ normals.push( v.normal[ j ] );
578
+
579
+ }
580
+
581
+ for ( let j = 0, jl = v.uv.length; j < jl; j ++ ) {
582
+
583
+ uvs.push( v.uv[ j ] );
584
+
585
+ }
586
+
587
+ for ( let j = 0; j < 4; j ++ ) {
588
+
589
+ skinIndices.push( v.skinIndices.length - 1 >= j ? v.skinIndices[ j ] : 0.0 );
590
+
591
+ }
592
+
593
+ for ( let j = 0; j < 4; j ++ ) {
594
+
595
+ skinWeights.push( v.skinWeights.length - 1 >= j ? v.skinWeights[ j ] : 0.0 );
596
+
597
+ }
598
+
599
+ }
600
+
601
+ // indices
602
+
603
+ for ( let i = 0; i < data.metadata.faceCount; i ++ ) {
604
+
605
+ const face = data.faces[ i ];
606
+
607
+ for ( let j = 0, jl = face.indices.length; j < jl; j ++ ) {
608
+
609
+ indices.push( face.indices[ j ] );
610
+
611
+ }
612
+
613
+ }
614
+
615
+ // groups
616
+
617
+ for ( let i = 0; i < data.metadata.materialCount; i ++ ) {
618
+
619
+ const material = data.materials[ i ];
620
+
621
+ groups.push( {
622
+ offset: offset * 3,
623
+ count: material.faceCount * 3
624
+ } );
625
+
626
+ offset += material.faceCount;
627
+
628
+ }
629
+
630
+ // bones
631
+
632
+ for ( let i = 0; i < data.metadata.rigidBodyCount; i ++ ) {
633
+
634
+ const body = data.rigidBodies[ i ];
635
+ let value = boneTypeTable[ body.boneIndex ];
636
+
637
+ // keeps greater number if already value is set without any special reasons
638
+ value = value === undefined ? body.type : Math.max( body.type, value );
639
+
640
+ boneTypeTable[ body.boneIndex ] = value;
641
+
642
+ }
643
+
644
+ for ( let i = 0; i < data.metadata.boneCount; i ++ ) {
645
+
646
+ const boneData = data.bones[ i ];
647
+
648
+ const bone = {
649
+ index: i,
650
+ transformationClass: boneData.transformationClass,
651
+ parent: boneData.parentIndex,
652
+ name: boneData.name,
653
+ pos: boneData.position.slice( 0, 3 ),
654
+ rotq: [ 0, 0, 0, 1 ],
655
+ scl: [ 1, 1, 1 ],
656
+ rigidBodyType: boneTypeTable[ i ] !== undefined ? boneTypeTable[ i ] : - 1
657
+ };
658
+
659
+ if ( bone.parent !== - 1 ) {
660
+
661
+ bone.pos[ 0 ] -= data.bones[ bone.parent ].position[ 0 ];
662
+ bone.pos[ 1 ] -= data.bones[ bone.parent ].position[ 1 ];
663
+ bone.pos[ 2 ] -= data.bones[ bone.parent ].position[ 2 ];
664
+
665
+ }
666
+
667
+ bones.push( bone );
668
+
669
+ }
670
+
671
+ // iks
672
+
673
+ // TODO: remove duplicated codes between PMD and PMX
674
+ if ( data.metadata.format === 'pmd' ) {
675
+
676
+ for ( let i = 0; i < data.metadata.ikCount; i ++ ) {
677
+
678
+ const ik = data.iks[ i ];
679
+
680
+ const param = {
681
+ target: ik.target,
682
+ effector: ik.effector,
683
+ iteration: ik.iteration,
684
+ maxAngle: ik.maxAngle * 4,
685
+ links: []
686
+ };
687
+
688
+ for ( let j = 0, jl = ik.links.length; j < jl; j ++ ) {
689
+
690
+ const link = {};
691
+ link.index = ik.links[ j ].index;
692
+ link.enabled = true;
693
+
694
+ if ( data.bones[ link.index ].name.indexOf( 'ひざ' ) >= 0 ) {
695
+
696
+ link.limitation = new Vector3( 1.0, 0.0, 0.0 );
697
+
698
+ }
699
+
700
+ param.links.push( link );
701
+
702
+ }
703
+
704
+ iks.push( param );
705
+
706
+ }
707
+
708
+ } else {
709
+
710
+ for ( let i = 0; i < data.metadata.boneCount; i ++ ) {
711
+
712
+ const ik = data.bones[ i ].ik;
713
+
714
+ if ( ik === undefined ) continue;
715
+
716
+ const param = {
717
+ target: i,
718
+ effector: ik.effector,
719
+ iteration: ik.iteration,
720
+ maxAngle: ik.maxAngle,
721
+ links: []
722
+ };
723
+
724
+ for ( let j = 0, jl = ik.links.length; j < jl; j ++ ) {
725
+
726
+ const link = {};
727
+ link.index = ik.links[ j ].index;
728
+ link.enabled = true;
729
+
730
+ if ( ik.links[ j ].angleLimitation === 1 ) {
731
+
732
+ // Revert if rotationMin/Max doesn't work well
733
+ // link.limitation = new Vector3( 1.0, 0.0, 0.0 );
734
+
735
+ const rotationMin = ik.links[ j ].lowerLimitationAngle;
736
+ const rotationMax = ik.links[ j ].upperLimitationAngle;
737
+
738
+ // Convert Left to Right coordinate by myself because
739
+ // MMDParser doesn't convert. It's a MMDParser's bug
740
+
741
+ const tmp1 = - rotationMax[ 0 ];
742
+ const tmp2 = - rotationMax[ 1 ];
743
+ rotationMax[ 0 ] = - rotationMin[ 0 ];
744
+ rotationMax[ 1 ] = - rotationMin[ 1 ];
745
+ rotationMin[ 0 ] = tmp1;
746
+ rotationMin[ 1 ] = tmp2;
747
+
748
+ link.rotationMin = new Vector3().fromArray( rotationMin );
749
+ link.rotationMax = new Vector3().fromArray( rotationMax );
750
+
751
+ }
752
+
753
+ param.links.push( link );
754
+
755
+ }
756
+
757
+ iks.push( param );
758
+
759
+ // Save the reference even from bone data for efficiently
760
+ // simulating PMX animation system
761
+ bones[ i ].ik = param;
762
+
763
+ }
764
+
765
+ }
766
+
767
+ // grants
768
+
769
+ if ( data.metadata.format === 'pmx' ) {
770
+
771
+ // bone index -> grant entry map
772
+ const grantEntryMap = {};
773
+
774
+ for ( let i = 0; i < data.metadata.boneCount; i ++ ) {
775
+
776
+ const boneData = data.bones[ i ];
777
+ const grant = boneData.grant;
778
+
779
+ if ( grant === undefined ) continue;
780
+
781
+ const param = {
782
+ index: i,
783
+ parentIndex: grant.parentIndex,
784
+ ratio: grant.ratio,
785
+ isLocal: grant.isLocal,
786
+ affectRotation: grant.affectRotation,
787
+ affectPosition: grant.affectPosition,
788
+ transformationClass: boneData.transformationClass
789
+ };
790
+
791
+ grantEntryMap[ i ] = { parent: null, children: [], param: param, visited: false };
792
+
793
+ }
794
+
795
+ const rootEntry = { parent: null, children: [], param: null, visited: false };
796
+
797
+ // Build a tree representing grant hierarchy
798
+
799
+ for ( const boneIndex in grantEntryMap ) {
800
+
801
+ const grantEntry = grantEntryMap[ boneIndex ];
802
+ const parentGrantEntry = grantEntryMap[ grantEntry.parentIndex ] || rootEntry;
803
+
804
+ grantEntry.parent = parentGrantEntry;
805
+ parentGrantEntry.children.push( grantEntry );
806
+
807
+ }
808
+
809
+ // Sort grant parameters from parents to children because
810
+ // grant uses parent's transform that parent's grant is already applied
811
+ // so grant should be applied in order from parents to children
812
+
813
+ function traverse( entry ) {
814
+
815
+ if ( entry.param ) {
816
+
817
+ grants.push( entry.param );
818
+
819
+ // Save the reference even from bone data for efficiently
820
+ // simulating PMX animation system
821
+ bones[ entry.param.index ].grant = entry.param;
822
+
823
+ }
824
+
825
+ entry.visited = true;
826
+
827
+ for ( let i = 0, il = entry.children.length; i < il; i ++ ) {
828
+
829
+ const child = entry.children[ i ];
830
+
831
+ // Cut off a loop if exists. (Is a grant loop invalid?)
832
+ if ( ! child.visited ) traverse( child );
833
+
834
+ }
835
+
836
+ }
837
+
838
+ traverse( rootEntry );
839
+
840
+ }
841
+
842
+ // morph
843
+
844
+ function updateAttributes( attribute, morph, ratio ) {
845
+
846
+ for ( let i = 0; i < morph.elementCount; i ++ ) {
847
+
848
+ const element = morph.elements[ i ];
849
+
850
+ let index;
851
+
852
+ if ( data.metadata.format === 'pmd' ) {
853
+
854
+ index = data.morphs[ 0 ].elements[ element.index ].index;
855
+
856
+ } else {
857
+
858
+ index = element.index;
859
+
860
+ }
861
+
862
+ attribute.array[ index * 3 + 0 ] += element.position[ 0 ] * ratio;
863
+ attribute.array[ index * 3 + 1 ] += element.position[ 1 ] * ratio;
864
+ attribute.array[ index * 3 + 2 ] += element.position[ 2 ] * ratio;
865
+
866
+ }
867
+
868
+ }
869
+
870
+ for ( let i = 0; i < data.metadata.morphCount; i ++ ) {
871
+
872
+ const morph = data.morphs[ i ];
873
+ const params = { name: morph.name };
874
+
875
+ const attribute = new Float32BufferAttribute( data.metadata.vertexCount * 3, 3 );
876
+ attribute.name = morph.name;
877
+
878
+ for ( let j = 0; j < data.metadata.vertexCount * 3; j ++ ) {
879
+
880
+ attribute.array[ j ] = positions[ j ];
881
+
882
+ }
883
+
884
+ if ( data.metadata.format === 'pmd' ) {
885
+
886
+ if ( i !== 0 ) {
887
+
888
+ updateAttributes( attribute, morph, 1.0 );
889
+
890
+ }
891
+
892
+ } else {
893
+
894
+ if ( morph.type === 0 ) { // group
895
+
896
+ for ( let j = 0; j < morph.elementCount; j ++ ) {
897
+
898
+ const morph2 = data.morphs[ morph.elements[ j ].index ];
899
+ const ratio = morph.elements[ j ].ratio;
900
+
901
+ if ( morph2.type === 1 ) {
902
+
903
+ updateAttributes( attribute, morph2, ratio );
904
+
905
+ } else {
906
+
907
+ // TODO: implement
908
+
909
+ }
910
+
911
+ }
912
+
913
+ } else if ( morph.type === 1 ) { // vertex
914
+
915
+ updateAttributes( attribute, morph, 1.0 );
916
+
917
+ } else if ( morph.type === 2 ) { // bone
918
+
919
+ // TODO: implement
920
+
921
+ } else if ( morph.type === 3 ) { // uv
922
+
923
+ // TODO: implement
924
+
925
+ } else if ( morph.type === 4 ) { // additional uv1
926
+
927
+ // TODO: implement
928
+
929
+ } else if ( morph.type === 5 ) { // additional uv2
930
+
931
+ // TODO: implement
932
+
933
+ } else if ( morph.type === 6 ) { // additional uv3
934
+
935
+ // TODO: implement
936
+
937
+ } else if ( morph.type === 7 ) { // additional uv4
938
+
939
+ // TODO: implement
940
+
941
+ } else if ( morph.type === 8 ) { // material
942
+
943
+ // TODO: implement
944
+
945
+ }
946
+
947
+ }
948
+
949
+ morphTargets.push( params );
950
+ morphPositions.push( attribute );
951
+
952
+ }
953
+
954
+ // rigid bodies from rigidBodies field.
955
+
956
+ for ( let i = 0; i < data.metadata.rigidBodyCount; i ++ ) {
957
+
958
+ const rigidBody = data.rigidBodies[ i ];
959
+ const params = {};
960
+
961
+ for ( const key in rigidBody ) {
962
+
963
+ params[ key ] = rigidBody[ key ];
964
+
965
+ }
966
+
967
+ /*
968
+ * RigidBody position parameter in PMX seems global position
969
+ * while the one in PMD seems offset from corresponding bone.
970
+ * So unify being offset.
971
+ */
972
+ if ( data.metadata.format === 'pmx' ) {
973
+
974
+ if ( params.boneIndex !== - 1 ) {
975
+
976
+ const bone = data.bones[ params.boneIndex ];
977
+ params.position[ 0 ] -= bone.position[ 0 ];
978
+ params.position[ 1 ] -= bone.position[ 1 ];
979
+ params.position[ 2 ] -= bone.position[ 2 ];
980
+
981
+ }
982
+
983
+ }
984
+
985
+ rigidBodies.push( params );
986
+
987
+ }
988
+
989
+ // constraints from constraints field.
990
+
991
+ for ( let i = 0; i < data.metadata.constraintCount; i ++ ) {
992
+
993
+ const constraint = data.constraints[ i ];
994
+ const params = {};
995
+
996
+ for ( const key in constraint ) {
997
+
998
+ params[ key ] = constraint[ key ];
999
+
1000
+ }
1001
+
1002
+ const bodyA = rigidBodies[ params.rigidBodyIndex1 ];
1003
+ const bodyB = rigidBodies[ params.rigidBodyIndex2 ];
1004
+
1005
+ // Refer to http://www20.atpages.jp/katwat/wp/?p=4135
1006
+ if ( bodyA.type !== 0 && bodyB.type === 2 ) {
1007
+
1008
+ if ( bodyA.boneIndex !== - 1 && bodyB.boneIndex !== - 1 &&
1009
+ data.bones[ bodyB.boneIndex ].parentIndex === bodyA.boneIndex ) {
1010
+
1011
+ bodyB.type = 1;
1012
+
1013
+ }
1014
+
1015
+ }
1016
+
1017
+ constraints.push( params );
1018
+
1019
+ }
1020
+
1021
+ // build BufferGeometry.
1022
+
1023
+ const geometry = new BufferGeometry();
1024
+
1025
+ geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
1026
+ geometry.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
1027
+ geometry.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
1028
+ geometry.setAttribute( 'skinIndex', new Uint16BufferAttribute( skinIndices, 4 ) );
1029
+ geometry.setAttribute( 'skinWeight', new Float32BufferAttribute( skinWeights, 4 ) );
1030
+ geometry.setIndex( indices );
1031
+
1032
+ for ( let i = 0, il = groups.length; i < il; i ++ ) {
1033
+
1034
+ geometry.addGroup( groups[ i ].offset, groups[ i ].count, i );
1035
+
1036
+ }
1037
+
1038
+ geometry.bones = bones;
1039
+
1040
+ geometry.morphTargets = morphTargets;
1041
+ geometry.morphAttributes.position = morphPositions;
1042
+ geometry.morphTargetsRelative = false;
1043
+
1044
+ geometry.userData.MMD = {
1045
+ bones: bones,
1046
+ iks: iks,
1047
+ grants: grants,
1048
+ rigidBodies: rigidBodies,
1049
+ constraints: constraints,
1050
+ format: data.metadata.format
1051
+ };
1052
+
1053
+ geometry.computeBoundingSphere();
1054
+
1055
+ return geometry;
1056
+
1057
+ }
1058
+
1059
+ }
1060
+
1061
+ //
1062
+
1063
+ /**
1064
+ * @param {THREE.LoadingManager} manager
1065
+ */
1066
+ class MaterialBuilder {
1067
+
1068
+ constructor( manager ) {
1069
+
1070
+ this.manager = manager;
1071
+
1072
+ this.textureLoader = new TextureLoader( this.manager );
1073
+ this.tgaLoader = null; // lazy generation
1074
+
1075
+ this.crossOrigin = 'anonymous';
1076
+ this.resourcePath = undefined;
1077
+
1078
+ }
1079
+
1080
+ /**
1081
+ * @param {string} crossOrigin
1082
+ * @return {MaterialBuilder}
1083
+ */
1084
+ setCrossOrigin( crossOrigin ) {
1085
+
1086
+ this.crossOrigin = crossOrigin;
1087
+ return this;
1088
+
1089
+ }
1090
+
1091
+ /**
1092
+ * @param {string} resourcePath
1093
+ * @return {MaterialBuilder}
1094
+ */
1095
+ setResourcePath( resourcePath ) {
1096
+
1097
+ this.resourcePath = resourcePath;
1098
+ return this;
1099
+
1100
+ }
1101
+
1102
+ /**
1103
+ * @param {Object} data - parsed PMD/PMX data
1104
+ * @param {BufferGeometry} geometry - some properties are dependend on geometry
1105
+ * @param {function} onProgress
1106
+ * @param {function} onError
1107
+ * @return {Array<MMDToonMaterial>}
1108
+ */
1109
+ build( data, geometry /*, onProgress, onError */ ) {
1110
+
1111
+ const materials = [];
1112
+
1113
+ const textures = {};
1114
+
1115
+ this.textureLoader.setCrossOrigin( this.crossOrigin );
1116
+
1117
+ // materials
1118
+
1119
+ for ( let i = 0; i < data.metadata.materialCount; i ++ ) {
1120
+
1121
+ const material = data.materials[ i ];
1122
+
1123
+ const params = { userData: { MMD: {} } };
1124
+
1125
+ if ( material.name !== undefined ) params.name = material.name;
1126
+
1127
+ /*
1128
+ * Color
1129
+ *
1130
+ * MMD MMDToonMaterial
1131
+ * ambient - emissive * a
1132
+ * (a = 1.0 without map texture or 0.2 with map texture)
1133
+ *
1134
+ * MMDToonMaterial doesn't have ambient. Set it to emissive instead.
1135
+ * It'll be too bright if material has map texture so using coef 0.2.
1136
+ */
1137
+ params.diffuse = new Color().setRGB(
1138
+ material.diffuse[ 0 ],
1139
+ material.diffuse[ 1 ],
1140
+ material.diffuse[ 2 ],
1141
+ SRGBColorSpace
1142
+ );
1143
+ params.opacity = material.diffuse[ 3 ];
1144
+ params.specular = new Color().setRGB( ...material.specular, SRGBColorSpace );
1145
+ params.shininess = material.shininess;
1146
+ params.emissive = new Color().setRGB( ...material.ambient, SRGBColorSpace );
1147
+ params.transparent = params.opacity !== 1.0;
1148
+
1149
+ //
1150
+
1151
+ params.fog = true;
1152
+
1153
+ // blend
1154
+
1155
+ params.blending = CustomBlending;
1156
+ params.blendSrc = SrcAlphaFactor;
1157
+ params.blendDst = OneMinusSrcAlphaFactor;
1158
+ params.blendSrcAlpha = SrcAlphaFactor;
1159
+ params.blendDstAlpha = DstAlphaFactor;
1160
+
1161
+ // side
1162
+
1163
+ if ( data.metadata.format === 'pmx' && ( material.flag & 0x1 ) === 1 ) {
1164
+
1165
+ params.side = DoubleSide;
1166
+
1167
+ } else {
1168
+
1169
+ params.side = params.opacity === 1.0 ? FrontSide : DoubleSide;
1170
+
1171
+ }
1172
+
1173
+ if ( data.metadata.format === 'pmd' ) {
1174
+
1175
+ // map, matcap
1176
+
1177
+ if ( material.fileName ) {
1178
+
1179
+ const fileName = material.fileName;
1180
+ const fileNames = fileName.split( '*' );
1181
+
1182
+ // fileNames[ 0 ]: mapFileName
1183
+ // fileNames[ 1 ]: matcapFileName( optional )
1184
+
1185
+ params.map = this._loadTexture( fileNames[ 0 ], textures );
1186
+
1187
+ if ( fileNames.length > 1 ) {
1188
+
1189
+ const extension = fileNames[ 1 ].slice( - 4 ).toLowerCase();
1190
+
1191
+ params.matcap = this._loadTexture(
1192
+ fileNames[ 1 ],
1193
+ textures
1194
+ );
1195
+
1196
+ params.matcapCombine = extension === '.sph'
1197
+ ? MultiplyOperation
1198
+ : AddOperation;
1199
+
1200
+ }
1201
+
1202
+ }
1203
+
1204
+ // gradientMap
1205
+
1206
+ const toonFileName = ( material.toonIndex === - 1 )
1207
+ ? 'toon00.bmp'
1208
+ : data.toonTextures[ material.toonIndex ].fileName;
1209
+
1210
+ params.gradientMap = this._loadTexture(
1211
+ toonFileName,
1212
+ textures,
1213
+ {
1214
+ isToonTexture: true,
1215
+ isDefaultToonTexture: this._isDefaultToonTexture( toonFileName )
1216
+ }
1217
+ );
1218
+
1219
+ // parameters for OutlineEffect
1220
+
1221
+ params.userData.outlineParameters = {
1222
+ thickness: material.edgeFlag === 1 ? 0.003 : 0.0,
1223
+ color: [ 0, 0, 0 ],
1224
+ alpha: 1.0,
1225
+ visible: material.edgeFlag === 1
1226
+ };
1227
+
1228
+ } else {
1229
+
1230
+ // map
1231
+
1232
+ if ( material.textureIndex !== - 1 ) {
1233
+
1234
+ params.map = this._loadTexture( data.textures[ material.textureIndex ], textures );
1235
+
1236
+ // Since PMX spec don't have standard to list map files except color map and env map,
1237
+ // we need to save file name for further mapping, like matching normal map file names after model loaded.
1238
+ // ref: https://gist.github.com/felixjones/f8a06bd48f9da9a4539f#texture
1239
+ params.userData.MMD.mapFileName = data.textures[ material.textureIndex ];
1240
+
1241
+ }
1242
+
1243
+ // matcap TODO: support m.envFlag === 3
1244
+
1245
+ if ( material.envTextureIndex !== - 1 && ( material.envFlag === 1 || material.envFlag == 2 ) ) {
1246
+
1247
+ params.matcap = this._loadTexture(
1248
+ data.textures[ material.envTextureIndex ],
1249
+ textures
1250
+ );
1251
+
1252
+ // Same as color map above, keep file name in userData for further usage.
1253
+ params.userData.MMD.matcapFileName = data.textures[ material.envTextureIndex ];
1254
+
1255
+ params.matcapCombine = material.envFlag === 1
1256
+ ? MultiplyOperation
1257
+ : AddOperation;
1258
+
1259
+ }
1260
+
1261
+ // gradientMap
1262
+
1263
+ let toonFileName, isDefaultToon;
1264
+
1265
+ if ( material.toonIndex === - 1 || material.toonFlag !== 0 ) {
1266
+
1267
+ toonFileName = 'toon' + ( '0' + ( material.toonIndex + 1 ) ).slice( - 2 ) + '.bmp';
1268
+ isDefaultToon = true;
1269
+
1270
+ } else {
1271
+
1272
+ toonFileName = data.textures[ material.toonIndex ];
1273
+ isDefaultToon = false;
1274
+
1275
+ }
1276
+
1277
+ params.gradientMap = this._loadTexture(
1278
+ toonFileName,
1279
+ textures,
1280
+ {
1281
+ isToonTexture: true,
1282
+ isDefaultToonTexture: isDefaultToon
1283
+ }
1284
+ );
1285
+
1286
+ // parameters for OutlineEffect
1287
+ params.userData.outlineParameters = {
1288
+ thickness: material.edgeSize / 300, // TODO: better calculation?
1289
+ color: material.edgeColor.slice( 0, 3 ),
1290
+ alpha: material.edgeColor[ 3 ],
1291
+ visible: ( material.flag & 0x10 ) !== 0 && material.edgeSize > 0.0
1292
+ };
1293
+
1294
+ }
1295
+
1296
+ if ( params.map !== undefined ) {
1297
+
1298
+ if ( ! params.transparent ) {
1299
+
1300
+ this._checkImageTransparency( params.map, geometry, i );
1301
+
1302
+ }
1303
+
1304
+ params.emissive.multiplyScalar( 0.2 );
1305
+
1306
+ }
1307
+
1308
+ materials.push( new MMDToonMaterial( params ) );
1309
+
1310
+ }
1311
+
1312
+ if ( data.metadata.format === 'pmx' ) {
1313
+
1314
+ // set transparent true if alpha morph is defined.
1315
+
1316
+ function checkAlphaMorph( elements, materials ) {
1317
+
1318
+ for ( let i = 0, il = elements.length; i < il; i ++ ) {
1319
+
1320
+ const element = elements[ i ];
1321
+
1322
+ if ( element.index === - 1 ) continue;
1323
+
1324
+ const material = materials[ element.index ];
1325
+
1326
+ if ( material.opacity !== element.diffuse[ 3 ] ) {
1327
+
1328
+ material.transparent = true;
1329
+
1330
+ }
1331
+
1332
+ }
1333
+
1334
+ }
1335
+
1336
+ for ( let i = 0, il = data.morphs.length; i < il; i ++ ) {
1337
+
1338
+ const morph = data.morphs[ i ];
1339
+ const elements = morph.elements;
1340
+
1341
+ if ( morph.type === 0 ) {
1342
+
1343
+ for ( let j = 0, jl = elements.length; j < jl; j ++ ) {
1344
+
1345
+ const morph2 = data.morphs[ elements[ j ].index ];
1346
+
1347
+ if ( morph2.type !== 8 ) continue;
1348
+
1349
+ checkAlphaMorph( morph2.elements, materials );
1350
+
1351
+ }
1352
+
1353
+ } else if ( morph.type === 8 ) {
1354
+
1355
+ checkAlphaMorph( elements, materials );
1356
+
1357
+ }
1358
+
1359
+ }
1360
+
1361
+ }
1362
+
1363
+ return materials;
1364
+
1365
+ }
1366
+
1367
+ // private methods
1368
+
1369
+ _getTGALoader() {
1370
+
1371
+ if ( this.tgaLoader === null ) {
1372
+
1373
+ if ( TGALoader === undefined ) {
1374
+
1375
+ throw new Error( 'THREE.MMDLoader: Import TGALoader' );
1376
+
1377
+ }
1378
+
1379
+ this.tgaLoader = new TGALoader( this.manager );
1380
+
1381
+ }
1382
+
1383
+ return this.tgaLoader;
1384
+
1385
+ }
1386
+
1387
+ _isDefaultToonTexture( name ) {
1388
+
1389
+ if ( name.length !== 10 ) return false;
1390
+
1391
+ return /toon(10|0[0-9])\.bmp/.test( name );
1392
+
1393
+ }
1394
+
1395
+ _loadTexture( filePath, textures, params, onProgress, onError ) {
1396
+
1397
+ params = params || {};
1398
+
1399
+ const scope = this;
1400
+
1401
+ let fullPath;
1402
+
1403
+ if ( params.isDefaultToonTexture === true ) {
1404
+
1405
+ let index;
1406
+
1407
+ try {
1408
+
1409
+ index = parseInt( filePath.match( /toon([0-9]{2})\.bmp$/ )[ 1 ] );
1410
+
1411
+ } catch ( e ) {
1412
+
1413
+ console.warn( 'THREE.MMDLoader: ' + filePath + ' seems like a '
1414
+ + 'not right default texture path. Using toon00.bmp instead.' );
1415
+
1416
+ index = 0;
1417
+
1418
+ }
1419
+
1420
+ fullPath = DEFAULT_TOON_TEXTURES[ index ];
1421
+
1422
+ } else {
1423
+
1424
+ fullPath = this.resourcePath + filePath;
1425
+
1426
+ }
1427
+
1428
+ if ( textures[ fullPath ] !== undefined ) return textures[ fullPath ];
1429
+
1430
+ let loader = this.manager.getHandler( fullPath );
1431
+
1432
+ if ( loader === null ) {
1433
+
1434
+ loader = ( filePath.slice( - 4 ).toLowerCase() === '.tga' )
1435
+ ? this._getTGALoader()
1436
+ : this.textureLoader;
1437
+
1438
+ }
1439
+
1440
+ const texture = loader.load( fullPath, function ( t ) {
1441
+
1442
+ // MMD toon texture is Axis-Y oriented
1443
+ // but Three.js gradient map is Axis-X oriented.
1444
+ // So here replaces the toon texture image with the rotated one.
1445
+ if ( params.isToonTexture === true ) {
1446
+
1447
+ t.image = scope._getRotatedImage( t.image );
1448
+
1449
+ t.magFilter = NearestFilter;
1450
+ t.minFilter = NearestFilter;
1451
+
1452
+ }
1453
+
1454
+ t.flipY = false;
1455
+ t.wrapS = RepeatWrapping;
1456
+ t.wrapT = RepeatWrapping;
1457
+ t.colorSpace = SRGBColorSpace;
1458
+
1459
+ for ( let i = 0; i < texture.readyCallbacks.length; i ++ ) {
1460
+
1461
+ texture.readyCallbacks[ i ]( texture );
1462
+
1463
+ }
1464
+
1465
+ delete texture.readyCallbacks;
1466
+
1467
+ }, onProgress, onError );
1468
+
1469
+ texture.readyCallbacks = [];
1470
+
1471
+ textures[ fullPath ] = texture;
1472
+
1473
+ return texture;
1474
+
1475
+ }
1476
+
1477
+ _getRotatedImage( image ) {
1478
+
1479
+ const canvas = document.createElement( 'canvas' );
1480
+ const context = canvas.getContext( '2d' );
1481
+
1482
+ const width = image.width;
1483
+ const height = image.height;
1484
+
1485
+ canvas.width = width;
1486
+ canvas.height = height;
1487
+
1488
+ context.clearRect( 0, 0, width, height );
1489
+ context.translate( width / 2.0, height / 2.0 );
1490
+ context.rotate( 0.5 * Math.PI ); // 90.0 * Math.PI / 180.0
1491
+ context.translate( - width / 2.0, - height / 2.0 );
1492
+ context.drawImage( image, 0, 0 );
1493
+
1494
+ return context.getImageData( 0, 0, width, height );
1495
+
1496
+ }
1497
+
1498
+ // Check if the partial image area used by the texture is transparent.
1499
+ _checkImageTransparency( map, geometry, groupIndex ) {
1500
+
1501
+ map.readyCallbacks.push( function ( texture ) {
1502
+
1503
+ // Is there any efficient ways?
1504
+ function createImageData( image ) {
1505
+
1506
+ const canvas = document.createElement( 'canvas' );
1507
+ canvas.width = image.width;
1508
+ canvas.height = image.height;
1509
+
1510
+ const context = canvas.getContext( '2d' );
1511
+ context.drawImage( image, 0, 0 );
1512
+
1513
+ return context.getImageData( 0, 0, canvas.width, canvas.height );
1514
+
1515
+ }
1516
+
1517
+ function detectImageTransparency( image, uvs, indices ) {
1518
+
1519
+ const width = image.width;
1520
+ const height = image.height;
1521
+ const data = image.data;
1522
+ const threshold = 253;
1523
+
1524
+ if ( data.length / ( width * height ) !== 4 ) return false;
1525
+
1526
+ for ( let i = 0; i < indices.length; i += 3 ) {
1527
+
1528
+ const centerUV = { x: 0.0, y: 0.0 };
1529
+
1530
+ for ( let j = 0; j < 3; j ++ ) {
1531
+
1532
+ const index = indices[ i * 3 + j ];
1533
+ const uv = { x: uvs[ index * 2 + 0 ], y: uvs[ index * 2 + 1 ] };
1534
+
1535
+ if ( getAlphaByUv( image, uv ) < threshold ) return true;
1536
+
1537
+ centerUV.x += uv.x;
1538
+ centerUV.y += uv.y;
1539
+
1540
+ }
1541
+
1542
+ centerUV.x /= 3;
1543
+ centerUV.y /= 3;
1544
+
1545
+ if ( getAlphaByUv( image, centerUV ) < threshold ) return true;
1546
+
1547
+ }
1548
+
1549
+ return false;
1550
+
1551
+ }
1552
+
1553
+ /*
1554
+ * This method expects
1555
+ * texture.flipY = false
1556
+ * texture.wrapS = RepeatWrapping
1557
+ * texture.wrapT = RepeatWrapping
1558
+ * TODO: more precise
1559
+ */
1560
+ function getAlphaByUv( image, uv ) {
1561
+
1562
+ const width = image.width;
1563
+ const height = image.height;
1564
+
1565
+ let x = Math.round( uv.x * width ) % width;
1566
+ let y = Math.round( uv.y * height ) % height;
1567
+
1568
+ if ( x < 0 ) x += width;
1569
+ if ( y < 0 ) y += height;
1570
+
1571
+ const index = y * width + x;
1572
+
1573
+ return image.data[ index * 4 + 3 ];
1574
+
1575
+ }
1576
+
1577
+ if ( texture.isCompressedTexture === true ) {
1578
+
1579
+ if ( NON_ALPHA_CHANNEL_FORMATS.includes( texture.format ) ) {
1580
+
1581
+ map.transparent = false;
1582
+
1583
+ } else {
1584
+
1585
+ // any other way to check transparency of CompressedTexture?
1586
+ map.transparent = true;
1587
+
1588
+ }
1589
+
1590
+ return;
1591
+
1592
+ }
1593
+
1594
+ const imageData = texture.image.data !== undefined
1595
+ ? texture.image
1596
+ : createImageData( texture.image );
1597
+
1598
+ const group = geometry.groups[ groupIndex ];
1599
+
1600
+ if ( detectImageTransparency(
1601
+ imageData,
1602
+ geometry.attributes.uv.array,
1603
+ geometry.index.array.slice( group.start, group.start + group.count ) ) ) {
1604
+
1605
+ map.transparent = true;
1606
+
1607
+ }
1608
+
1609
+ } );
1610
+
1611
+ }
1612
+
1613
+ }
1614
+
1615
+ //
1616
+
1617
+ class AnimationBuilder {
1618
+
1619
+ /**
1620
+ * @param {Object} vmd - parsed VMD data
1621
+ * @param {SkinnedMesh} mesh - tracks will be fitting to mesh
1622
+ * @return {AnimationClip}
1623
+ */
1624
+ build( vmd, mesh ) {
1625
+
1626
+ // combine skeletal and morph animations
1627
+
1628
+ const tracks = this.buildSkeletalAnimation( vmd, mesh ).tracks;
1629
+ const tracks2 = this.buildMorphAnimation( vmd, mesh ).tracks;
1630
+
1631
+ for ( let i = 0, il = tracks2.length; i < il; i ++ ) {
1632
+
1633
+ tracks.push( tracks2[ i ] );
1634
+
1635
+ }
1636
+
1637
+ return new AnimationClip( '', - 1, tracks );
1638
+
1639
+ }
1640
+
1641
+ /**
1642
+ * @param {Object} vmd - parsed VMD data
1643
+ * @param {SkinnedMesh} mesh - tracks will be fitting to mesh
1644
+ * @return {AnimationClip}
1645
+ */
1646
+ buildSkeletalAnimation( vmd, mesh ) {
1647
+
1648
+ function pushInterpolation( array, interpolation, index ) {
1649
+
1650
+ array.push( interpolation[ index + 0 ] / 127 ); // x1
1651
+ array.push( interpolation[ index + 8 ] / 127 ); // x2
1652
+ array.push( interpolation[ index + 4 ] / 127 ); // y1
1653
+ array.push( interpolation[ index + 12 ] / 127 ); // y2
1654
+
1655
+ }
1656
+
1657
+ const tracks = [];
1658
+
1659
+ const motions = {};
1660
+ const bones = mesh.skeleton.bones;
1661
+ const boneNameDictionary = {};
1662
+
1663
+ for ( let i = 0, il = bones.length; i < il; i ++ ) {
1664
+
1665
+ boneNameDictionary[ bones[ i ].name ] = true;
1666
+
1667
+ }
1668
+
1669
+ for ( let i = 0; i < vmd.metadata.motionCount; i ++ ) {
1670
+
1671
+ const motion = vmd.motions[ i ];
1672
+ const boneName = motion.boneName;
1673
+
1674
+ if ( boneNameDictionary[ boneName ] === undefined ) continue;
1675
+
1676
+ motions[ boneName ] = motions[ boneName ] || [];
1677
+ motions[ boneName ].push( motion );
1678
+
1679
+ }
1680
+
1681
+ for ( const key in motions ) {
1682
+
1683
+ const array = motions[ key ];
1684
+
1685
+ array.sort( function ( a, b ) {
1686
+
1687
+ return a.frameNum - b.frameNum;
1688
+
1689
+ } );
1690
+
1691
+ const times = [];
1692
+ const positions = [];
1693
+ const rotations = [];
1694
+ const pInterpolations = [];
1695
+ const rInterpolations = [];
1696
+
1697
+ const basePosition = mesh.skeleton.getBoneByName( key ).position.toArray();
1698
+
1699
+ for ( let i = 0, il = array.length; i < il; i ++ ) {
1700
+
1701
+ const time = array[ i ].frameNum / 30;
1702
+ const position = array[ i ].position;
1703
+ const rotation = array[ i ].rotation;
1704
+ const interpolation = array[ i ].interpolation;
1705
+
1706
+ times.push( time );
1707
+
1708
+ for ( let j = 0; j < 3; j ++ ) positions.push( basePosition[ j ] + position[ j ] );
1709
+ for ( let j = 0; j < 4; j ++ ) rotations.push( rotation[ j ] );
1710
+ for ( let j = 0; j < 3; j ++ ) pushInterpolation( pInterpolations, interpolation, j );
1711
+
1712
+ pushInterpolation( rInterpolations, interpolation, 3 );
1713
+
1714
+ }
1715
+
1716
+ const targetName = '.bones[' + key + ']';
1717
+
1718
+ tracks.push( this._createTrack( targetName + '.position', VectorKeyframeTrack, times, positions, pInterpolations ) );
1719
+ tracks.push( this._createTrack( targetName + '.quaternion', QuaternionKeyframeTrack, times, rotations, rInterpolations ) );
1720
+
1721
+ }
1722
+
1723
+ return new AnimationClip( '', - 1, tracks );
1724
+
1725
+ }
1726
+
1727
+ /**
1728
+ * @param {Object} vmd - parsed VMD data
1729
+ * @param {SkinnedMesh} mesh - tracks will be fitting to mesh
1730
+ * @return {AnimationClip}
1731
+ */
1732
+ buildMorphAnimation( vmd, mesh ) {
1733
+
1734
+ const tracks = [];
1735
+
1736
+ const morphs = {};
1737
+ const morphTargetDictionary = mesh.morphTargetDictionary;
1738
+
1739
+ for ( let i = 0; i < vmd.metadata.morphCount; i ++ ) {
1740
+
1741
+ const morph = vmd.morphs[ i ];
1742
+ const morphName = morph.morphName;
1743
+
1744
+ if ( morphTargetDictionary[ morphName ] === undefined ) continue;
1745
+
1746
+ morphs[ morphName ] = morphs[ morphName ] || [];
1747
+ morphs[ morphName ].push( morph );
1748
+
1749
+ }
1750
+
1751
+ for ( const key in morphs ) {
1752
+
1753
+ const array = morphs[ key ];
1754
+
1755
+ array.sort( function ( a, b ) {
1756
+
1757
+ return a.frameNum - b.frameNum;
1758
+
1759
+ } );
1760
+
1761
+ const times = [];
1762
+ const values = [];
1763
+
1764
+ for ( let i = 0, il = array.length; i < il; i ++ ) {
1765
+
1766
+ times.push( array[ i ].frameNum / 30 );
1767
+ values.push( array[ i ].weight );
1768
+
1769
+ }
1770
+
1771
+ tracks.push( new NumberKeyframeTrack( '.morphTargetInfluences[' + morphTargetDictionary[ key ] + ']', times, values ) );
1772
+
1773
+ }
1774
+
1775
+ return new AnimationClip( '', - 1, tracks );
1776
+
1777
+ }
1778
+
1779
+ /**
1780
+ * @param {Object} vmd - parsed VMD data
1781
+ * @return {AnimationClip}
1782
+ */
1783
+ buildCameraAnimation( vmd ) {
1784
+
1785
+ function pushVector3( array, vec ) {
1786
+
1787
+ array.push( vec.x );
1788
+ array.push( vec.y );
1789
+ array.push( vec.z );
1790
+
1791
+ }
1792
+
1793
+ function pushQuaternion( array, q ) {
1794
+
1795
+ array.push( q.x );
1796
+ array.push( q.y );
1797
+ array.push( q.z );
1798
+ array.push( q.w );
1799
+
1800
+ }
1801
+
1802
+ function pushInterpolation( array, interpolation, index ) {
1803
+
1804
+ array.push( interpolation[ index * 4 + 0 ] / 127 ); // x1
1805
+ array.push( interpolation[ index * 4 + 1 ] / 127 ); // x2
1806
+ array.push( interpolation[ index * 4 + 2 ] / 127 ); // y1
1807
+ array.push( interpolation[ index * 4 + 3 ] / 127 ); // y2
1808
+
1809
+ }
1810
+
1811
+ const cameras = vmd.cameras === undefined ? [] : vmd.cameras.slice();
1812
+
1813
+ cameras.sort( function ( a, b ) {
1814
+
1815
+ return a.frameNum - b.frameNum;
1816
+
1817
+ } );
1818
+
1819
+ const times = [];
1820
+ const centers = [];
1821
+ const quaternions = [];
1822
+ const positions = [];
1823
+ const fovs = [];
1824
+
1825
+ const cInterpolations = [];
1826
+ const qInterpolations = [];
1827
+ const pInterpolations = [];
1828
+ const fInterpolations = [];
1829
+
1830
+ const quaternion = new Quaternion();
1831
+ const euler = new Euler();
1832
+ const position = new Vector3();
1833
+ const center = new Vector3();
1834
+
1835
+ for ( let i = 0, il = cameras.length; i < il; i ++ ) {
1836
+
1837
+ const motion = cameras[ i ];
1838
+
1839
+ const time = motion.frameNum / 30;
1840
+ const pos = motion.position;
1841
+ const rot = motion.rotation;
1842
+ const distance = motion.distance;
1843
+ const fov = motion.fov;
1844
+ const interpolation = motion.interpolation;
1845
+
1846
+ times.push( time );
1847
+
1848
+ position.set( 0, 0, - distance );
1849
+ center.set( pos[ 0 ], pos[ 1 ], pos[ 2 ] );
1850
+
1851
+ euler.set( - rot[ 0 ], - rot[ 1 ], - rot[ 2 ] );
1852
+ quaternion.setFromEuler( euler );
1853
+
1854
+ position.add( center );
1855
+ position.applyQuaternion( quaternion );
1856
+
1857
+ pushVector3( centers, center );
1858
+ pushQuaternion( quaternions, quaternion );
1859
+ pushVector3( positions, position );
1860
+
1861
+ fovs.push( fov );
1862
+
1863
+ for ( let j = 0; j < 3; j ++ ) {
1864
+
1865
+ pushInterpolation( cInterpolations, interpolation, j );
1866
+
1867
+ }
1868
+
1869
+ pushInterpolation( qInterpolations, interpolation, 3 );
1870
+
1871
+ // use the same parameter for x, y, z axis.
1872
+ for ( let j = 0; j < 3; j ++ ) {
1873
+
1874
+ pushInterpolation( pInterpolations, interpolation, 4 );
1875
+
1876
+ }
1877
+
1878
+ pushInterpolation( fInterpolations, interpolation, 5 );
1879
+
1880
+ }
1881
+
1882
+ const tracks = [];
1883
+
1884
+ // I expect an object whose name 'target' exists under THREE.Camera
1885
+ tracks.push( this._createTrack( 'target.position', VectorKeyframeTrack, times, centers, cInterpolations ) );
1886
+
1887
+ tracks.push( this._createTrack( '.quaternion', QuaternionKeyframeTrack, times, quaternions, qInterpolations ) );
1888
+ tracks.push( this._createTrack( '.position', VectorKeyframeTrack, times, positions, pInterpolations ) );
1889
+ tracks.push( this._createTrack( '.fov', NumberKeyframeTrack, times, fovs, fInterpolations ) );
1890
+
1891
+ return new AnimationClip( '', - 1, tracks );
1892
+
1893
+ }
1894
+
1895
+ // private method
1896
+
1897
+ _createTrack( node, typedKeyframeTrack, times, values, interpolations ) {
1898
+
1899
+ /*
1900
+ * optimizes here not to let KeyframeTrackPrototype optimize
1901
+ * because KeyframeTrackPrototype optimizes times and values but
1902
+ * doesn't optimize interpolations.
1903
+ */
1904
+ if ( times.length > 2 ) {
1905
+
1906
+ times = times.slice();
1907
+ values = values.slice();
1908
+ interpolations = interpolations.slice();
1909
+
1910
+ const stride = values.length / times.length;
1911
+ const interpolateStride = interpolations.length / times.length;
1912
+
1913
+ let index = 1;
1914
+
1915
+ for ( let aheadIndex = 2, endIndex = times.length; aheadIndex < endIndex; aheadIndex ++ ) {
1916
+
1917
+ for ( let i = 0; i < stride; i ++ ) {
1918
+
1919
+ if ( values[ index * stride + i ] !== values[ ( index - 1 ) * stride + i ] ||
1920
+ values[ index * stride + i ] !== values[ aheadIndex * stride + i ] ) {
1921
+
1922
+ index ++;
1923
+ break;
1924
+
1925
+ }
1926
+
1927
+ }
1928
+
1929
+ if ( aheadIndex > index ) {
1930
+
1931
+ times[ index ] = times[ aheadIndex ];
1932
+
1933
+ for ( let i = 0; i < stride; i ++ ) {
1934
+
1935
+ values[ index * stride + i ] = values[ aheadIndex * stride + i ];
1936
+
1937
+ }
1938
+
1939
+ for ( let i = 0; i < interpolateStride; i ++ ) {
1940
+
1941
+ interpolations[ index * interpolateStride + i ] = interpolations[ aheadIndex * interpolateStride + i ];
1942
+
1943
+ }
1944
+
1945
+ }
1946
+
1947
+ }
1948
+
1949
+ times.length = index + 1;
1950
+ values.length = ( index + 1 ) * stride;
1951
+ interpolations.length = ( index + 1 ) * interpolateStride;
1952
+
1953
+ }
1954
+
1955
+ const track = new typedKeyframeTrack( node, times, values );
1956
+
1957
+ track.createInterpolant = function InterpolantFactoryMethodCubicBezier( result ) {
1958
+
1959
+ return new CubicBezierInterpolation( this.times, this.values, this.getValueSize(), result, new Float32Array( interpolations ) );
1960
+
1961
+ };
1962
+
1963
+ return track;
1964
+
1965
+ }
1966
+
1967
+ }
1968
+
1969
+ // interpolation
1970
+
1971
+ class CubicBezierInterpolation extends Interpolant {
1972
+
1973
+ constructor( parameterPositions, sampleValues, sampleSize, resultBuffer, params ) {
1974
+
1975
+ super( parameterPositions, sampleValues, sampleSize, resultBuffer );
1976
+
1977
+ this.interpolationParams = params;
1978
+
1979
+ }
1980
+
1981
+ interpolate_( i1, t0, t, t1 ) {
1982
+
1983
+ const result = this.resultBuffer;
1984
+ const values = this.sampleValues;
1985
+ const stride = this.valueSize;
1986
+ const params = this.interpolationParams;
1987
+
1988
+ const offset1 = i1 * stride;
1989
+ const offset0 = offset1 - stride;
1990
+
1991
+ // No interpolation if next key frame is in one frame in 30fps.
1992
+ // This is from MMD animation spec.
1993
+ // '1.5' is for precision loss. times are Float32 in Three.js Animation system.
1994
+ const weight1 = ( ( t1 - t0 ) < 1 / 30 * 1.5 ) ? 0.0 : ( t - t0 ) / ( t1 - t0 );
1995
+
1996
+ if ( stride === 4 ) { // Quaternion
1997
+
1998
+ const x1 = params[ i1 * 4 + 0 ];
1999
+ const x2 = params[ i1 * 4 + 1 ];
2000
+ const y1 = params[ i1 * 4 + 2 ];
2001
+ const y2 = params[ i1 * 4 + 3 ];
2002
+
2003
+ const ratio = this._calculate( x1, x2, y1, y2, weight1 );
2004
+
2005
+ Quaternion.slerpFlat( result, 0, values, offset0, values, offset1, ratio );
2006
+
2007
+ } else if ( stride === 3 ) { // Vector3
2008
+
2009
+ for ( let i = 0; i !== stride; ++ i ) {
2010
+
2011
+ const x1 = params[ i1 * 12 + i * 4 + 0 ];
2012
+ const x2 = params[ i1 * 12 + i * 4 + 1 ];
2013
+ const y1 = params[ i1 * 12 + i * 4 + 2 ];
2014
+ const y2 = params[ i1 * 12 + i * 4 + 3 ];
2015
+
2016
+ const ratio = this._calculate( x1, x2, y1, y2, weight1 );
2017
+
2018
+ result[ i ] = values[ offset0 + i ] * ( 1 - ratio ) + values[ offset1 + i ] * ratio;
2019
+
2020
+ }
2021
+
2022
+ } else { // Number
2023
+
2024
+ const x1 = params[ i1 * 4 + 0 ];
2025
+ const x2 = params[ i1 * 4 + 1 ];
2026
+ const y1 = params[ i1 * 4 + 2 ];
2027
+ const y2 = params[ i1 * 4 + 3 ];
2028
+
2029
+ const ratio = this._calculate( x1, x2, y1, y2, weight1 );
2030
+
2031
+ result[ 0 ] = values[ offset0 ] * ( 1 - ratio ) + values[ offset1 ] * ratio;
2032
+
2033
+ }
2034
+
2035
+ return result;
2036
+
2037
+ }
2038
+
2039
+ _calculate( x1, x2, y1, y2, x ) {
2040
+
2041
+ /*
2042
+ * Cubic Bezier curves
2043
+ * https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Cubic_B.C3.A9zier_curves
2044
+ *
2045
+ * B(t) = ( 1 - t ) ^ 3 * P0
2046
+ * + 3 * ( 1 - t ) ^ 2 * t * P1
2047
+ * + 3 * ( 1 - t ) * t^2 * P2
2048
+ * + t ^ 3 * P3
2049
+ * ( 0 <= t <= 1 )
2050
+ *
2051
+ * MMD uses Cubic Bezier curves for bone and camera animation interpolation.
2052
+ * http://d.hatena.ne.jp/edvakf/20111016/1318716097
2053
+ *
2054
+ * x = ( 1 - t ) ^ 3 * x0
2055
+ * + 3 * ( 1 - t ) ^ 2 * t * x1
2056
+ * + 3 * ( 1 - t ) * t^2 * x2
2057
+ * + t ^ 3 * x3
2058
+ * y = ( 1 - t ) ^ 3 * y0
2059
+ * + 3 * ( 1 - t ) ^ 2 * t * y1
2060
+ * + 3 * ( 1 - t ) * t^2 * y2
2061
+ * + t ^ 3 * y3
2062
+ * ( x0 = 0, y0 = 0 )
2063
+ * ( x3 = 1, y3 = 1 )
2064
+ * ( 0 <= t, x1, x2, y1, y2 <= 1 )
2065
+ *
2066
+ * Here solves this equation with Bisection method,
2067
+ * https://en.wikipedia.org/wiki/Bisection_method
2068
+ * gets t, and then calculate y.
2069
+ *
2070
+ * f(t) = 3 * ( 1 - t ) ^ 2 * t * x1
2071
+ * + 3 * ( 1 - t ) * t^2 * x2
2072
+ * + t ^ 3 - x = 0
2073
+ *
2074
+ * (Another option: Newton's method
2075
+ * https://en.wikipedia.org/wiki/Newton%27s_method)
2076
+ */
2077
+
2078
+ let c = 0.5;
2079
+ let t = c;
2080
+ let s = 1.0 - t;
2081
+ const loop = 15;
2082
+ const eps = 1e-5;
2083
+ const math = Math;
2084
+
2085
+ let sst3, stt3, ttt;
2086
+
2087
+ for ( let i = 0; i < loop; i ++ ) {
2088
+
2089
+ sst3 = 3.0 * s * s * t;
2090
+ stt3 = 3.0 * s * t * t;
2091
+ ttt = t * t * t;
2092
+
2093
+ const ft = ( sst3 * x1 ) + ( stt3 * x2 ) + ( ttt ) - x;
2094
+
2095
+ if ( math.abs( ft ) < eps ) break;
2096
+
2097
+ c /= 2.0;
2098
+
2099
+ t += ( ft < 0 ) ? c : - c;
2100
+ s = 1.0 - t;
2101
+
2102
+ }
2103
+
2104
+ return ( sst3 * y1 ) + ( stt3 * y2 ) + ttt;
2105
+
2106
+ }
2107
+
2108
+ }
2109
+
2110
+ class MMDToonMaterial extends ShaderMaterial {
2111
+
2112
+ constructor( parameters ) {
2113
+
2114
+ super();
2115
+
2116
+ this.isMMDToonMaterial = true;
2117
+
2118
+ this.type = 'MMDToonMaterial';
2119
+
2120
+ this._matcapCombine = AddOperation;
2121
+ this.emissiveIntensity = 1.0;
2122
+ this.normalMapType = TangentSpaceNormalMap;
2123
+
2124
+ this.combine = MultiplyOperation;
2125
+
2126
+ this.wireframeLinecap = 'round';
2127
+ this.wireframeLinejoin = 'round';
2128
+
2129
+ this.flatShading = false;
2130
+
2131
+ this.lights = true;
2132
+
2133
+ this.vertexShader = MMDToonShader.vertexShader;
2134
+ this.fragmentShader = MMDToonShader.fragmentShader;
2135
+
2136
+ this.defines = Object.assign( {}, MMDToonShader.defines );
2137
+ Object.defineProperty( this, 'matcapCombine', {
2138
+
2139
+ get: function () {
2140
+
2141
+ return this._matcapCombine;
2142
+
2143
+ },
2144
+
2145
+ set: function ( value ) {
2146
+
2147
+ this._matcapCombine = value;
2148
+
2149
+ switch ( value ) {
2150
+
2151
+ case MultiplyOperation:
2152
+ this.defines.MATCAP_BLENDING_MULTIPLY = true;
2153
+ delete this.defines.MATCAP_BLENDING_ADD;
2154
+ break;
2155
+
2156
+ default:
2157
+ case AddOperation:
2158
+ this.defines.MATCAP_BLENDING_ADD = true;
2159
+ delete this.defines.MATCAP_BLENDING_MULTIPLY;
2160
+ break;
2161
+
2162
+ }
2163
+
2164
+ },
2165
+
2166
+ } );
2167
+
2168
+ this.uniforms = UniformsUtils.clone( MMDToonShader.uniforms );
2169
+
2170
+ // merged from MeshToon/Phong/MatcapMaterial
2171
+ const exposePropertyNames = [
2172
+ 'specular',
2173
+ 'opacity',
2174
+ 'diffuse',
2175
+
2176
+ 'map',
2177
+ 'matcap',
2178
+ 'gradientMap',
2179
+
2180
+ 'lightMap',
2181
+ 'lightMapIntensity',
2182
+
2183
+ 'aoMap',
2184
+ 'aoMapIntensity',
2185
+
2186
+ 'emissive',
2187
+ 'emissiveMap',
2188
+
2189
+ 'bumpMap',
2190
+ 'bumpScale',
2191
+
2192
+ 'normalMap',
2193
+ 'normalScale',
2194
+
2195
+ 'displacemantBias',
2196
+ 'displacemantMap',
2197
+ 'displacemantScale',
2198
+
2199
+ 'specularMap',
2200
+
2201
+ 'alphaMap',
2202
+
2203
+ 'reflectivity',
2204
+ 'refractionRatio',
2205
+ ];
2206
+ for ( const propertyName of exposePropertyNames ) {
2207
+
2208
+ Object.defineProperty( this, propertyName, {
2209
+
2210
+ get: function () {
2211
+
2212
+ return this.uniforms[ propertyName ].value;
2213
+
2214
+ },
2215
+
2216
+ set: function ( value ) {
2217
+
2218
+ this.uniforms[ propertyName ].value = value;
2219
+
2220
+ },
2221
+
2222
+ } );
2223
+
2224
+ }
2225
+
2226
+ // Special path for shininess to handle zero shininess properly
2227
+ this._shininess = 30;
2228
+ Object.defineProperty( this, 'shininess', {
2229
+
2230
+ get: function () {
2231
+
2232
+ return this._shininess;
2233
+
2234
+ },
2235
+
2236
+ set: function ( value ) {
2237
+
2238
+ this._shininess = value;
2239
+ this.uniforms.shininess.value = Math.max( this._shininess, 1e-4 ); // To prevent pow( 0.0, 0.0 )
2240
+
2241
+ },
2242
+
2243
+ } );
2244
+
2245
+ Object.defineProperty(
2246
+ this,
2247
+ 'color',
2248
+ Object.getOwnPropertyDescriptor( this, 'diffuse' )
2249
+ );
2250
+
2251
+ this.setValues( parameters );
2252
+
2253
+ }
2254
+
2255
+ copy( source ) {
2256
+
2257
+ super.copy( source );
2258
+
2259
+ this.matcapCombine = source.matcapCombine;
2260
+ this.emissiveIntensity = source.emissiveIntensity;
2261
+ this.normalMapType = source.normalMapType;
2262
+
2263
+ this.combine = source.combine;
2264
+
2265
+ this.wireframeLinecap = source.wireframeLinecap;
2266
+ this.wireframeLinejoin = source.wireframeLinejoin;
2267
+
2268
+ this.flatShading = source.flatShading;
2269
+
2270
+ return this;
2271
+
2272
+ }
2273
+
2274
+ }
2275
+
2276
+ export { MMDLoader };