@vgai/engine 0.5.0 → 0.5.1

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 (538) hide show
  1. package/package.json +1 -1
  2. package/schemas/engine-capabilities.json +4 -4
  3. package/schemas/vgai-game.schema.json +2 -2
  4. package/src/adapter/authoring.ts +42 -0
  5. package/src/adapter/index.ts +3 -0
  6. package/src/adapter/ingest/overlay-apply.ts +50 -6
  7. package/src/adapter/ingest/scene-capture.ts +51 -2
  8. package/src/adapter/vgai-scene-game-adapter.ts +24 -0
  9. package/src/manifest/schema.ts +7 -3
  10. package/src/runtime/create-runtime.ts +97 -0
  11. package/src/runtime/game.ts +11 -1
  12. package/src/scene/asset-ref-check.ts +1 -1
  13. package/src/scene/scene-loader.ts +2 -2
  14. package/src/scene/user-data.ts +18 -0
  15. package/src/world3d-react/behavior.tsx +19 -11
  16. package/src/world3d-react/r3f-adapter.tsx +8 -0
  17. package/dist/adapter/adapter-surface.d.ts +0 -30
  18. package/dist/adapter/adapter-surface.d.ts.map +0 -1
  19. package/dist/adapter/adapter-surface.js +0 -18
  20. package/dist/adapter/authoring.d.ts +0 -461
  21. package/dist/adapter/authoring.d.ts.map +0 -1
  22. package/dist/adapter/authoring.js +0 -22
  23. package/dist/adapter/colyseus-networking-adapter.d.ts +0 -43
  24. package/dist/adapter/colyseus-networking-adapter.d.ts.map +0 -1
  25. package/dist/adapter/colyseus-networking-adapter.js +0 -38
  26. package/dist/adapter/first-party-systems.d.ts +0 -38
  27. package/dist/adapter/first-party-systems.d.ts.map +0 -1
  28. package/dist/adapter/first-party-systems.js +0 -77
  29. package/dist/adapter/game-adapter.d.ts +0 -133
  30. package/dist/adapter/game-adapter.d.ts.map +0 -1
  31. package/dist/adapter/game-adapter.js +0 -10
  32. package/dist/adapter/host-context.d.ts +0 -71
  33. package/dist/adapter/host-context.d.ts.map +0 -1
  34. package/dist/adapter/host-context.js +0 -16
  35. package/dist/adapter/index.d.ts +0 -22
  36. package/dist/adapter/index.d.ts.map +0 -1
  37. package/dist/adapter/index.js +0 -15
  38. package/dist/adapter/ingest/game-contract.d.ts +0 -53
  39. package/dist/adapter/ingest/game-contract.d.ts.map +0 -1
  40. package/dist/adapter/ingest/game-contract.js +0 -30
  41. package/dist/adapter/ingest/overlay-applier.d.ts +0 -118
  42. package/dist/adapter/ingest/overlay-applier.d.ts.map +0 -1
  43. package/dist/adapter/ingest/overlay-applier.js +0 -132
  44. package/dist/adapter/ingest/overlay-apply.d.ts +0 -60
  45. package/dist/adapter/ingest/overlay-apply.d.ts.map +0 -1
  46. package/dist/adapter/ingest/overlay-apply.js +0 -101
  47. package/dist/adapter/ingest/overlay-file.d.ts +0 -79
  48. package/dist/adapter/ingest/overlay-file.d.ts.map +0 -1
  49. package/dist/adapter/ingest/overlay-file.js +0 -66
  50. package/dist/adapter/ingest/overlay-report.d.ts +0 -113
  51. package/dist/adapter/ingest/overlay-report.d.ts.map +0 -1
  52. package/dist/adapter/ingest/overlay-report.js +0 -103
  53. package/dist/adapter/ingest/scene-capture.d.ts +0 -97
  54. package/dist/adapter/ingest/scene-capture.d.ts.map +0 -1
  55. package/dist/adapter/ingest/scene-capture.js +0 -248
  56. package/dist/adapter/ingest/upstream-pin.d.ts +0 -47
  57. package/dist/adapter/ingest/upstream-pin.d.ts.map +0 -1
  58. package/dist/adapter/ingest/upstream-pin.js +0 -50
  59. package/dist/adapter/loop-gate-report.d.ts +0 -34
  60. package/dist/adapter/loop-gate-report.d.ts.map +0 -1
  61. package/dist/adapter/loop-gate-report.js +0 -37
  62. package/dist/adapter/rapier-physics-adapter.d.ts +0 -12
  63. package/dist/adapter/rapier-physics-adapter.d.ts.map +0 -1
  64. package/dist/adapter/rapier-physics-adapter.js +0 -46
  65. package/dist/adapter/system-adapter.d.ts +0 -206
  66. package/dist/adapter/system-adapter.d.ts.map +0 -1
  67. package/dist/adapter/system-adapter.js +0 -13
  68. package/dist/adapter/transform.d.ts +0 -18
  69. package/dist/adapter/transform.d.ts.map +0 -1
  70. package/dist/adapter/transform.js +0 -1
  71. package/dist/adapter/vgai-scene-game-adapter.d.ts +0 -108
  72. package/dist/adapter/vgai-scene-game-adapter.d.ts.map +0 -1
  73. package/dist/adapter/vgai-scene-game-adapter.js +0 -762
  74. package/dist/ai/navigation.d.ts +0 -64
  75. package/dist/ai/navigation.d.ts.map +0 -1
  76. package/dist/ai/navigation.js +0 -133
  77. package/dist/animation/anim-graph-types.d.ts +0 -25
  78. package/dist/animation/anim-graph-types.d.ts.map +0 -1
  79. package/dist/animation/anim-graph-types.js +0 -1
  80. package/dist/animation/animation-clock.d.ts +0 -213
  81. package/dist/animation/animation-clock.d.ts.map +0 -1
  82. package/dist/animation/animation-clock.js +0 -301
  83. package/dist/animation/blend-node.d.ts +0 -22
  84. package/dist/animation/blend-node.d.ts.map +0 -1
  85. package/dist/animation/blend-node.js +0 -97
  86. package/dist/animation/camera-ownership.d.ts +0 -250
  87. package/dist/animation/camera-ownership.d.ts.map +0 -1
  88. package/dist/animation/camera-ownership.js +0 -169
  89. package/dist/animation/cinematic-cues.d.ts +0 -200
  90. package/dist/animation/cinematic-cues.d.ts.map +0 -1
  91. package/dist/animation/cinematic-cues.js +0 -213
  92. package/dist/animation/clip-map.d.ts +0 -12
  93. package/dist/animation/clip-map.d.ts.map +0 -1
  94. package/dist/animation/clip-map.js +0 -37
  95. package/dist/animation/gsap-registration.d.ts +0 -119
  96. package/dist/animation/gsap-registration.d.ts.map +0 -1
  97. package/dist/animation/gsap-registration.js +0 -92
  98. package/dist/animation/theatre-clock-binding.d.ts +0 -89
  99. package/dist/animation/theatre-clock-binding.d.ts.map +0 -1
  100. package/dist/animation/theatre-clock-binding.js +0 -29
  101. package/dist/animation/theatre-director.d.ts +0 -242
  102. package/dist/animation/theatre-director.d.ts.map +0 -1
  103. package/dist/animation/theatre-director.js +0 -235
  104. package/dist/animation/theatre-object-binding.d.ts +0 -305
  105. package/dist/animation/theatre-object-binding.d.ts.map +0 -1
  106. package/dist/animation/theatre-object-binding.js +0 -351
  107. package/dist/animation/xstate-animation-binding.d.ts +0 -56
  108. package/dist/animation/xstate-animation-binding.d.ts.map +0 -1
  109. package/dist/animation/xstate-animation-binding.js +0 -331
  110. package/dist/animation/xstate-animation-meta.d.ts +0 -266
  111. package/dist/animation/xstate-animation-meta.d.ts.map +0 -1
  112. package/dist/animation/xstate-animation-meta.js +0 -252
  113. package/dist/assets.d.ts +0 -26
  114. package/dist/assets.d.ts.map +0 -1
  115. package/dist/assets.js +0 -55
  116. package/dist/audio/index.d.ts +0 -4
  117. package/dist/audio/index.d.ts.map +0 -1
  118. package/dist/audio/index.js +0 -24
  119. package/dist/audio/tone-clock-binding.d.ts +0 -75
  120. package/dist/audio/tone-clock-binding.d.ts.map +0 -1
  121. package/dist/audio/tone-clock-binding.js +0 -29
  122. package/dist/audio/tone-context.d.ts +0 -114
  123. package/dist/audio/tone-context.d.ts.map +0 -1
  124. package/dist/audio/tone-context.js +0 -39
  125. package/dist/audio/tone-offline-render.d.ts +0 -90
  126. package/dist/audio/tone-offline-render.d.ts.map +0 -1
  127. package/dist/audio/tone-offline-render.js +0 -56
  128. package/dist/audio/wav-encode.d.ts +0 -38
  129. package/dist/audio/wav-encode.d.ts.map +0 -1
  130. package/dist/audio/wav-encode.js +0 -97
  131. package/dist/character/cloth-sim.d.ts +0 -179
  132. package/dist/character/cloth-sim.d.ts.map +0 -1
  133. package/dist/character/cloth-sim.js +0 -334
  134. package/dist/character/spring-chain.d.ts +0 -135
  135. package/dist/character/spring-chain.d.ts.map +0 -1
  136. package/dist/character/spring-chain.js +0 -165
  137. package/dist/core/game-loop.d.ts +0 -42
  138. package/dist/core/game-loop.d.ts.map +0 -1
  139. package/dist/core/game-loop.js +0 -167
  140. package/dist/core/seeded-random.d.ts +0 -69
  141. package/dist/core/seeded-random.d.ts.map +0 -1
  142. package/dist/core/seeded-random.js +0 -121
  143. package/dist/core/system-runner.d.ts +0 -120
  144. package/dist/core/system-runner.d.ts.map +0 -1
  145. package/dist/core/system-runner.js +0 -297
  146. package/dist/core/types.d.ts +0 -92
  147. package/dist/core/types.d.ts.map +0 -1
  148. package/dist/core/types.js +0 -25
  149. package/dist/data/data-asset.d.ts +0 -101
  150. package/dist/data/data-asset.d.ts.map +0 -1
  151. package/dist/data/data-asset.js +0 -122
  152. package/dist/data/data-check-core.d.ts +0 -110
  153. package/dist/data/data-check-core.d.ts.map +0 -1
  154. package/dist/data/data-check-core.js +0 -178
  155. package/dist/data/data-ref.d.ts +0 -79
  156. package/dist/data/data-ref.d.ts.map +0 -1
  157. package/dist/data/data-ref.js +0 -130
  158. package/dist/data/vite-plugin-data.d.ts +0 -79
  159. package/dist/data/vite-plugin-data.d.ts.map +0 -1
  160. package/dist/data/vite-plugin-data.js +0 -217
  161. package/dist/dev/console-bridge.d.ts +0 -22
  162. package/dist/dev/console-bridge.d.ts.map +0 -1
  163. package/dist/dev/console-bridge.js +0 -71
  164. package/dist/dev/debug-draw.d.ts +0 -24
  165. package/dist/dev/debug-draw.d.ts.map +0 -1
  166. package/dist/dev/debug-draw.js +0 -73
  167. package/dist/dev/logger.d.ts +0 -30
  168. package/dist/dev/logger.d.ts.map +0 -1
  169. package/dist/dev/logger.js +0 -90
  170. package/dist/dev/performance-profiler.d.ts +0 -60
  171. package/dist/dev/performance-profiler.d.ts.map +0 -1
  172. package/dist/dev/performance-profiler.js +0 -181
  173. package/dist/dev/webgl-gpu-timer.d.ts +0 -8
  174. package/dist/dev/webgl-gpu-timer.d.ts.map +0 -1
  175. package/dist/dev/webgl-gpu-timer.js +0 -52
  176. package/dist/ecs/component-manager.d.ts +0 -205
  177. package/dist/ecs/component-manager.d.ts.map +0 -1
  178. package/dist/ecs/component-manager.js +0 -706
  179. package/dist/ecs/game-component.d.ts +0 -146
  180. package/dist/ecs/game-component.d.ts.map +0 -1
  181. package/dist/ecs/game-component.js +0 -141
  182. package/dist/ecs/hmr-swap-report.d.ts +0 -53
  183. package/dist/ecs/hmr-swap-report.d.ts.map +0 -1
  184. package/dist/ecs/hmr-swap-report.js +0 -55
  185. package/dist/humanoid/bake.operation.d.ts +0 -119
  186. package/dist/humanoid/bake.operation.d.ts.map +0 -1
  187. package/dist/humanoid/bake.operation.js +0 -228
  188. package/dist/humanoid/body.d.ts +0 -101
  189. package/dist/humanoid/body.d.ts.map +0 -1
  190. package/dist/humanoid/body.js +0 -530
  191. package/dist/humanoid/clips.d.ts +0 -62
  192. package/dist/humanoid/clips.d.ts.map +0 -1
  193. package/dist/humanoid/clips.js +0 -121
  194. package/dist/humanoid/compose.d.ts +0 -75
  195. package/dist/humanoid/compose.d.ts.map +0 -1
  196. package/dist/humanoid/compose.js +0 -176
  197. package/dist/humanoid/generate.d.ts +0 -92
  198. package/dist/humanoid/generate.d.ts.map +0 -1
  199. package/dist/humanoid/generate.js +0 -124
  200. package/dist/humanoid/index.d.ts +0 -24
  201. package/dist/humanoid/index.d.ts.map +0 -1
  202. package/dist/humanoid/index.js +0 -18
  203. package/dist/humanoid/schema.d.ts +0 -35
  204. package/dist/humanoid/schema.d.ts.map +0 -1
  205. package/dist/humanoid/schema.js +0 -87
  206. package/dist/humanoid/skeleton.d.ts +0 -103
  207. package/dist/humanoid/skeleton.d.ts.map +0 -1
  208. package/dist/humanoid/skeleton.js +0 -289
  209. package/dist/index.d.ts +0 -37
  210. package/dist/index.d.ts.map +0 -1
  211. package/dist/index.js +0 -30
  212. package/dist/input/input-manager.d.ts +0 -945
  213. package/dist/input/input-manager.d.ts.map +0 -1
  214. package/dist/input/input-manager.js +0 -2207
  215. package/dist/input/input-types.d.ts +0 -174
  216. package/dist/input/input-types.d.ts.map +0 -1
  217. package/dist/input/input-types.js +0 -1
  218. package/dist/input/prompt-labels.d.ts +0 -21
  219. package/dist/input/prompt-labels.d.ts.map +0 -1
  220. package/dist/input/prompt-labels.js +0 -121
  221. package/dist/input/rebind-controller.d.ts +0 -59
  222. package/dist/input/rebind-controller.d.ts.map +0 -1
  223. package/dist/input/rebind-controller.js +0 -85
  224. package/dist/input/schema.d.ts +0 -16
  225. package/dist/input/schema.d.ts.map +0 -1
  226. package/dist/input/schema.js +0 -228
  227. package/dist/loader.d.ts +0 -43
  228. package/dist/loader.d.ts.map +0 -1
  229. package/dist/loader.js +0 -59
  230. package/dist/manifest/index.d.ts +0 -5
  231. package/dist/manifest/index.d.ts.map +0 -1
  232. package/dist/manifest/index.js +0 -8
  233. package/dist/manifest/load-file.d.ts +0 -4
  234. package/dist/manifest/load-file.d.ts.map +0 -1
  235. package/dist/manifest/load-file.js +0 -14
  236. package/dist/manifest/load.d.ts +0 -144
  237. package/dist/manifest/load.d.ts.map +0 -1
  238. package/dist/manifest/load.js +0 -273
  239. package/dist/manifest/schema.d.ts +0 -230
  240. package/dist/manifest/schema.d.ts.map +0 -1
  241. package/dist/manifest/schema.js +0 -394
  242. package/dist/physics/collision-system.d.ts +0 -41
  243. package/dist/physics/collision-system.d.ts.map +0 -1
  244. package/dist/physics/collision-system.js +0 -64
  245. package/dist/physics/physics-registry.d.ts +0 -45
  246. package/dist/physics/physics-registry.d.ts.map +0 -1
  247. package/dist/physics/physics-registry.js +0 -65
  248. package/dist/physics/transform-writer.d.ts +0 -16
  249. package/dist/physics/transform-writer.d.ts.map +0 -1
  250. package/dist/physics/transform-writer.js +0 -38
  251. package/dist/physics/trigger-dispatch.d.ts +0 -24
  252. package/dist/physics/trigger-dispatch.d.ts.map +0 -1
  253. package/dist/physics/trigger-dispatch.js +0 -80
  254. package/dist/react/game-state.d.ts +0 -156
  255. package/dist/react/game-state.d.ts.map +0 -1
  256. package/dist/react/game-state.js +0 -222
  257. package/dist/react/root-adapter.d.ts +0 -11
  258. package/dist/react/root-adapter.d.ts.map +0 -1
  259. package/dist/react/root-adapter.js +0 -41
  260. package/dist/react/unmanaged-root-detector.d.ts +0 -12
  261. package/dist/react/unmanaged-root-detector.d.ts.map +0 -1
  262. package/dist/react/unmanaged-root-detector.js +0 -45
  263. package/dist/react/use-data.d.ts +0 -60
  264. package/dist/react/use-data.d.ts.map +0 -1
  265. package/dist/react/use-data.js +0 -101
  266. package/dist/react/use-selection.d.ts +0 -75
  267. package/dist/react/use-selection.d.ts.map +0 -1
  268. package/dist/react/use-selection.js +0 -90
  269. package/dist/render/auto-batcher.d.ts +0 -34
  270. package/dist/render/auto-batcher.d.ts.map +0 -1
  271. package/dist/render/auto-batcher.js +0 -140
  272. package/dist/render/render-batch-system.d.ts +0 -33
  273. package/dist/render/render-batch-system.d.ts.map +0 -1
  274. package/dist/render/render-batch-system.js +0 -230
  275. package/dist/render/render-features.d.ts +0 -47
  276. package/dist/render/render-features.d.ts.map +0 -1
  277. package/dist/render/render-features.js +0 -105
  278. package/dist/render/render-settings.d.ts +0 -36
  279. package/dist/render/render-settings.d.ts.map +0 -1
  280. package/dist/render/render-settings.js +0 -51
  281. package/dist/runtime/create-runtime.d.ts +0 -249
  282. package/dist/runtime/create-runtime.d.ts.map +0 -1
  283. package/dist/runtime/create-runtime.js +0 -641
  284. package/dist/runtime/debug-bridge.d.ts +0 -257
  285. package/dist/runtime/debug-bridge.d.ts.map +0 -1
  286. package/dist/runtime/debug-bridge.js +0 -224
  287. package/dist/runtime/debug-registry.d.ts +0 -288
  288. package/dist/runtime/debug-registry.d.ts.map +0 -1
  289. package/dist/runtime/debug-registry.js +0 -513
  290. package/dist/runtime/frame-selector-cache.d.ts +0 -41
  291. package/dist/runtime/frame-selector-cache.d.ts.map +0 -1
  292. package/dist/runtime/frame-selector-cache.js +0 -65
  293. package/dist/runtime/game.d.ts +0 -496
  294. package/dist/runtime/game.d.ts.map +0 -1
  295. package/dist/runtime/game.js +0 -741
  296. package/dist/runtime/gameplay-rng-trap.d.ts +0 -48
  297. package/dist/runtime/gameplay-rng-trap.d.ts.map +0 -1
  298. package/dist/runtime/gameplay-rng-trap.js +0 -96
  299. package/dist/runtime/input-router.d.ts +0 -78
  300. package/dist/runtime/input-router.d.ts.map +0 -1
  301. package/dist/runtime/input-router.js +0 -171
  302. package/dist/runtime/mount-game.d.ts +0 -129
  303. package/dist/runtime/mount-game.d.ts.map +0 -1
  304. package/dist/runtime/mount-game.js +0 -152
  305. package/dist/runtime/mount-manifest.d.ts +0 -173
  306. package/dist/runtime/mount-manifest.d.ts.map +0 -1
  307. package/dist/runtime/mount-manifest.js +0 -297
  308. package/dist/runtime/render-audio-control.d.ts +0 -110
  309. package/dist/runtime/render-audio-control.d.ts.map +0 -1
  310. package/dist/runtime/render-audio-control.js +0 -111
  311. package/dist/runtime/render-control.d.ts +0 -291
  312. package/dist/runtime/render-control.d.ts.map +0 -1
  313. package/dist/runtime/render-control.js +0 -264
  314. package/dist/runtime/render-seed.d.ts +0 -57
  315. package/dist/runtime/render-seed.d.ts.map +0 -1
  316. package/dist/runtime/render-seed.js +0 -74
  317. package/dist/runtime/state-bridge.d.ts +0 -61
  318. package/dist/runtime/state-bridge.d.ts.map +0 -1
  319. package/dist/runtime/state-bridge.js +0 -63
  320. package/dist/runtime/types.d.ts +0 -253
  321. package/dist/runtime/types.d.ts.map +0 -1
  322. package/dist/runtime/types.js +0 -1
  323. package/dist/scene/asset-loaders.d.ts +0 -79
  324. package/dist/scene/asset-loaders.d.ts.map +0 -1
  325. package/dist/scene/asset-loaders.js +0 -141
  326. package/dist/scene/asset-paths.d.ts +0 -11
  327. package/dist/scene/asset-paths.d.ts.map +0 -1
  328. package/dist/scene/asset-paths.js +0 -108
  329. package/dist/scene/asset-ref-check.d.ts +0 -88
  330. package/dist/scene/asset-ref-check.d.ts.map +0 -1
  331. package/dist/scene/asset-ref-check.js +0 -214
  332. package/dist/scene/asset-registry.d.ts +0 -38
  333. package/dist/scene/asset-registry.d.ts.map +0 -1
  334. package/dist/scene/asset-registry.js +0 -66
  335. package/dist/scene/collider-dimensions.d.ts +0 -63
  336. package/dist/scene/collider-dimensions.d.ts.map +0 -1
  337. package/dist/scene/collider-dimensions.js +0 -98
  338. package/dist/scene/component-registry.d.ts +0 -22
  339. package/dist/scene/component-registry.d.ts.map +0 -1
  340. package/dist/scene/component-registry.js +0 -37
  341. package/dist/scene/defaults.d.ts +0 -252
  342. package/dist/scene/defaults.d.ts.map +0 -1
  343. package/dist/scene/defaults.js +0 -151
  344. package/dist/scene/geometries/index.d.ts +0 -8
  345. package/dist/scene/geometries/index.d.ts.map +0 -1
  346. package/dist/scene/geometries/index.js +0 -7
  347. package/dist/scene/geometries/terrain.d.ts +0 -2
  348. package/dist/scene/geometries/terrain.d.ts.map +0 -1
  349. package/dist/scene/geometries/terrain.js +0 -37
  350. package/dist/scene/geometry-registry.d.ts +0 -24
  351. package/dist/scene/geometry-registry.d.ts.map +0 -1
  352. package/dist/scene/geometry-registry.js +0 -20
  353. package/dist/scene/instance-registry.d.ts +0 -36
  354. package/dist/scene/instance-registry.d.ts.map +0 -1
  355. package/dist/scene/instance-registry.js +0 -55
  356. package/dist/scene/instancers/grid.d.ts +0 -2
  357. package/dist/scene/instancers/grid.d.ts.map +0 -1
  358. package/dist/scene/instancers/grid.js +0 -36
  359. package/dist/scene/instancers/index.d.ts +0 -8
  360. package/dist/scene/instancers/index.d.ts.map +0 -1
  361. package/dist/scene/instancers/index.js +0 -7
  362. package/dist/scene/light-camera-factory.d.ts +0 -23
  363. package/dist/scene/light-camera-factory.d.ts.map +0 -1
  364. package/dist/scene/light-camera-factory.js +0 -68
  365. package/dist/scene/material-factory.d.ts +0 -17
  366. package/dist/scene/material-factory.d.ts.map +0 -1
  367. package/dist/scene/material-factory.js +0 -197
  368. package/dist/scene/material-registry.d.ts +0 -40
  369. package/dist/scene/material-registry.d.ts.map +0 -1
  370. package/dist/scene/material-registry.js +0 -44
  371. package/dist/scene/materials/index.d.ts +0 -8
  372. package/dist/scene/materials/index.d.ts.map +0 -1
  373. package/dist/scene/materials/index.js +0 -7
  374. package/dist/scene/materials/water.d.ts +0 -2
  375. package/dist/scene/materials/water.d.ts.map +0 -1
  376. package/dist/scene/materials/water.js +0 -54
  377. package/dist/scene/parse.d.ts +0 -23
  378. package/dist/scene/parse.d.ts.map +0 -1
  379. package/dist/scene/parse.js +0 -179
  380. package/dist/scene/particles-factory.d.ts +0 -33
  381. package/dist/scene/particles-factory.d.ts.map +0 -1
  382. package/dist/scene/particles-factory.js +0 -282
  383. package/dist/scene/scene-apply.d.ts +0 -109
  384. package/dist/scene/scene-apply.d.ts.map +0 -1
  385. package/dist/scene/scene-apply.js +0 -370
  386. package/dist/scene/scene-diff-schema.d.ts +0 -285
  387. package/dist/scene/scene-diff-schema.d.ts.map +0 -1
  388. package/dist/scene/scene-diff-schema.js +0 -92
  389. package/dist/scene/scene-diff-types.d.ts +0 -40
  390. package/dist/scene/scene-diff-types.d.ts.map +0 -1
  391. package/dist/scene/scene-diff-types.js +0 -14
  392. package/dist/scene/scene-loader.d.ts +0 -167
  393. package/dist/scene/scene-loader.d.ts.map +0 -1
  394. package/dist/scene/scene-loader.js +0 -1211
  395. package/dist/scene/scene-query.d.ts +0 -11
  396. package/dist/scene/scene-query.d.ts.map +0 -1
  397. package/dist/scene/scene-query.js +0 -63
  398. package/dist/scene/scene-types.d.ts +0 -10
  399. package/dist/scene/scene-types.d.ts.map +0 -1
  400. package/dist/scene/scene-types.js +0 -8
  401. package/dist/scene/scene-version.d.ts +0 -26
  402. package/dist/scene/scene-version.d.ts.map +0 -1
  403. package/dist/scene/scene-version.js +0 -34
  404. package/dist/scene/schema/animation.d.ts +0 -8
  405. package/dist/scene/schema/animation.d.ts.map +0 -1
  406. package/dist/scene/schema/animation.js +0 -42
  407. package/dist/scene/schema/audio.d.ts +0 -13
  408. package/dist/scene/schema/audio.d.ts.map +0 -1
  409. package/dist/scene/schema/audio.js +0 -22
  410. package/dist/scene/schema/camera.d.ts +0 -28
  411. package/dist/scene/schema/camera.d.ts.map +0 -1
  412. package/dist/scene/schema/camera.js +0 -17
  413. package/dist/scene/schema/collider.d.ts +0 -40
  414. package/dist/scene/schema/collider.d.ts.map +0 -1
  415. package/dist/scene/schema/collider.js +0 -55
  416. package/dist/scene/schema/entity-ref.d.ts +0 -31
  417. package/dist/scene/schema/entity-ref.d.ts.map +0 -1
  418. package/dist/scene/schema/entity-ref.js +0 -61
  419. package/dist/scene/schema/entity.d.ts +0 -1036
  420. package/dist/scene/schema/entity.d.ts.map +0 -1
  421. package/dist/scene/schema/entity.js +0 -153
  422. package/dist/scene/schema/environment.d.ts +0 -425
  423. package/dist/scene/schema/environment.d.ts.map +0 -1
  424. package/dist/scene/schema/environment.js +0 -357
  425. package/dist/scene/schema/index.d.ts +0 -37
  426. package/dist/scene/schema/index.d.ts.map +0 -1
  427. package/dist/scene/schema/index.js +0 -19
  428. package/dist/scene/schema/instances.d.ts +0 -14
  429. package/dist/scene/schema/instances.d.ts.map +0 -1
  430. package/dist/scene/schema/instances.js +0 -28
  431. package/dist/scene/schema/joint.d.ts +0 -23
  432. package/dist/scene/schema/joint.d.ts.map +0 -1
  433. package/dist/scene/schema/joint.js +0 -23
  434. package/dist/scene/schema/light.d.ts +0 -38
  435. package/dist/scene/schema/light.d.ts.map +0 -1
  436. package/dist/scene/schema/light.js +0 -26
  437. package/dist/scene/schema/material.d.ts +0 -199
  438. package/dist/scene/schema/material.d.ts.map +0 -1
  439. package/dist/scene/schema/material.js +0 -103
  440. package/dist/scene/schema/mesh.d.ts +0 -48
  441. package/dist/scene/schema/mesh.d.ts.map +0 -1
  442. package/dist/scene/schema/mesh.js +0 -82
  443. package/dist/scene/schema/particles.d.ts +0 -2178
  444. package/dist/scene/schema/particles.d.ts.map +0 -1
  445. package/dist/scene/schema/particles.js +0 -321
  446. package/dist/scene/schema/physics.d.ts +0 -56
  447. package/dist/scene/schema/physics.d.ts.map +0 -1
  448. package/dist/scene/schema/physics.js +0 -37
  449. package/dist/scene/schema/scene-file.d.ts +0 -303
  450. package/dist/scene/schema/scene-file.d.ts.map +0 -1
  451. package/dist/scene/schema/scene-file.js +0 -256
  452. package/dist/scene/schema/shadow.d.ts +0 -28
  453. package/dist/scene/schema/shadow.d.ts.map +0 -1
  454. package/dist/scene/schema/shadow.js +0 -20
  455. package/dist/scene/schema/spline.d.ts +0 -25
  456. package/dist/scene/schema/spline.d.ts.map +0 -1
  457. package/dist/scene/schema/spline.js +0 -15
  458. package/dist/scene/schema/tuples.d.ts +0 -12
  459. package/dist/scene/schema/tuples.d.ts.map +0 -1
  460. package/dist/scene/schema/tuples.js +0 -14
  461. package/dist/scene/user-data.d.ts +0 -185
  462. package/dist/scene/user-data.d.ts.map +0 -1
  463. package/dist/scene/user-data.js +0 -144
  464. package/dist/setup/setup-audio.d.ts +0 -20
  465. package/dist/setup/setup-audio.d.ts.map +0 -1
  466. package/dist/setup/setup-audio.js +0 -41
  467. package/dist/setup/setup-particles.d.ts +0 -17
  468. package/dist/setup/setup-particles.d.ts.map +0 -1
  469. package/dist/setup/setup-particles.js +0 -16
  470. package/dist/setup/setup-physics.d.ts +0 -25
  471. package/dist/setup/setup-physics.d.ts.map +0 -1
  472. package/dist/setup/setup-physics.js +0 -51
  473. package/dist/setup/setup-renderer.d.ts +0 -69
  474. package/dist/setup/setup-renderer.d.ts.map +0 -1
  475. package/dist/setup/setup-renderer.js +0 -363
  476. package/dist/tools/define-tool.d.ts +0 -130
  477. package/dist/tools/define-tool.d.ts.map +0 -1
  478. package/dist/tools/define-tool.js +0 -96
  479. package/dist/world2d/authoring-2d.d.ts +0 -80
  480. package/dist/world2d/authoring-2d.d.ts.map +0 -1
  481. package/dist/world2d/authoring-2d.js +0 -195
  482. package/dist/world2d/capture-to-scene2d.d.ts +0 -5
  483. package/dist/world2d/capture-to-scene2d.d.ts.map +0 -1
  484. package/dist/world2d/capture-to-scene2d.js +0 -49
  485. package/dist/world2d/collision-2d.d.ts +0 -52
  486. package/dist/world2d/collision-2d.d.ts.map +0 -1
  487. package/dist/world2d/collision-2d.js +0 -70
  488. package/dist/world2d/components-2d.d.ts +0 -47
  489. package/dist/world2d/components-2d.d.ts.map +0 -1
  490. package/dist/world2d/components-2d.js +0 -77
  491. package/dist/world2d/index.d.ts +0 -34
  492. package/dist/world2d/index.d.ts.map +0 -1
  493. package/dist/world2d/index.js +0 -32
  494. package/dist/world2d/ingest-iframe-2d.d.ts +0 -82
  495. package/dist/world2d/ingest-iframe-2d.d.ts.map +0 -1
  496. package/dist/world2d/ingest-iframe-2d.js +0 -166
  497. package/dist/world2d/ingest2d.d.ts +0 -97
  498. package/dist/world2d/ingest2d.d.ts.map +0 -1
  499. package/dist/world2d/ingest2d.js +0 -40
  500. package/dist/world2d/physics2d-registry.d.ts +0 -24
  501. package/dist/world2d/physics2d-registry.d.ts.map +0 -1
  502. package/dist/world2d/physics2d-registry.js +0 -38
  503. package/dist/world2d/pixi-game-adapter.d.ts +0 -107
  504. package/dist/world2d/pixi-game-adapter.d.ts.map +0 -1
  505. package/dist/world2d/pixi-game-adapter.js +0 -210
  506. package/dist/world2d/pixi-surface.d.ts +0 -39
  507. package/dist/world2d/pixi-surface.d.ts.map +0 -1
  508. package/dist/world2d/pixi-surface.js +0 -47
  509. package/dist/world2d/scene-capture-2d.d.ts +0 -43
  510. package/dist/world2d/scene-capture-2d.d.ts.map +0 -1
  511. package/dist/world2d/scene-capture-2d.js +0 -92
  512. package/dist/world2d/scene2d-loader.d.ts +0 -27
  513. package/dist/world2d/scene2d-loader.d.ts.map +0 -1
  514. package/dist/world2d/scene2d-loader.js +0 -275
  515. package/dist/world2d/schema/entity2d.d.ts +0 -102
  516. package/dist/world2d/schema/entity2d.d.ts.map +0 -1
  517. package/dist/world2d/schema/entity2d.js +0 -119
  518. package/dist/world2d/schema/physics2d.d.ts +0 -46
  519. package/dist/world2d/schema/physics2d.d.ts.map +0 -1
  520. package/dist/world2d/schema/physics2d.js +0 -45
  521. package/dist/world2d/schema/sprite.d.ts +0 -42
  522. package/dist/world2d/schema/sprite.d.ts.map +0 -1
  523. package/dist/world2d/schema/sprite.js +0 -63
  524. package/dist/world2d/schema/tilemap.d.ts +0 -15
  525. package/dist/world2d/schema/tilemap.d.ts.map +0 -1
  526. package/dist/world2d/schema/tilemap.js +0 -19
  527. package/dist/world2d/schema/tuples2d.d.ts +0 -20
  528. package/dist/world2d/schema/tuples2d.d.ts.map +0 -1
  529. package/dist/world2d/schema/tuples2d.js +0 -19
  530. package/dist/world2d/system-adapters-2d.d.ts +0 -16
  531. package/dist/world2d/system-adapters-2d.d.ts.map +0 -1
  532. package/dist/world2d/system-adapters-2d.js +0 -37
  533. package/dist/world2d/transform-writer-2d.d.ts +0 -16
  534. package/dist/world2d/transform-writer-2d.d.ts.map +0 -1
  535. package/dist/world2d/transform-writer-2d.js +0 -22
  536. package/dist/world2d/types.d.ts +0 -59
  537. package/dist/world2d/types.d.ts.map +0 -1
  538. package/dist/world2d/types.js +0 -1
@@ -1,334 +0,0 @@
1
- /**
2
- * Character primitive — Jolt soft-body cloth grids (capes, skirts, banners)
3
- * on top of the raw `jolt-physics` WASM bindings.
4
- *
5
- * THIN COMPOSITION HELPER, not a wrapper (CLAUDE.md "use libraries
6
- * directly"): every export assembles the library's own objects
7
- * (`Jolt.SoftBodySharedSettings`, `Jolt.Body`, `Jolt.JoltInterface`) —
8
- * nothing from the library is re-exported. This file never imports the WASM
9
- * module itself — the caller does the async `JoltInit()` and passes the
10
- * resolved module in, mirroring `setup-physics.ts`'s `setupPhysics(rapier:
11
- * typeof RAPIER, ...)` pattern for Rapier. `import type Jolt from
12
- * 'jolt-physics/wasm-compat'` below is TYPE-ONLY (erased at compile time —
13
- * no runtime WASM import here).
14
- *
15
- * Sharp edges this module exists partly to contain (see the mission brief /
16
- * `cloth-hair-bench/jolt-cloth.ts`'s header for the full discovery):
17
- * - `Body.GetMotionProperties()` needs the `Jolt.castObject` downcast to
18
- * `Jolt.SoftBodyMotionProperties` to reach `GetVertex`.
19
- * - `SoftBodySharedSettings.CreateConstraints` takes a POINTER-typed
20
- * 1-element `ArraySoftBodySharedSettingsVertexAttributes` (push_back,
21
- * not resize+at — `.at()` on these embind vectors returns a copy).
22
- * - Kinematic pins must set BOTH `SoftBodyVertex.mPosition` and
23
- * `.mVelocity` (finite-differenced) every tick, or the cloth's own
24
- * constraint solver fights a teleporting anchor.
25
- * - NO per-frame embind allocations (reviewer finding on Phase 1's
26
- * spike, which leaked a `new Jolt.Vec3(...)`/`new Jolt.RVec3(...)` per
27
- * pinned vertex per frame): `tick()` below preallocates ONE `Jolt.Vec3`
28
- * for position and ONE for velocity and reuses them via `.Set(...)` —
29
- * embind property setters (`vertex.mPosition = tmpVec3`) copy the value
30
- * in, so reassigning the SAME wrapper object across many vertices in one
31
- * frame is safe. `KinematicCollider.moveTo` does the same with one
32
- * `Jolt.RVec3` + one `Jolt.Quat` (identity, orientation is not simulated
33
- * here) allocated once at construction.
34
- * - CONSTRUCTION-TIME embind temporaries need `Jolt.destroy(...)` too, once
35
- * Jolt has copied their data out (reviewer finding on Phase 2 — these
36
- * were leaking WASM heap per build/dispose cycle even with `tick()`
37
- * itself allocation-free). Two different lifetimes are at play:
38
- * - Per-vertex/per-face grid temporaries (`SoftBodySharedSettingsVertex`
39
- * + its `Float3`, `SoftBodySharedSettingsFace`, the single
40
- * `vertexAttr`) are copied BY VALUE into `sharedSettings`'s own
41
- * storage the instant `push_back`/the property setter runs — freed
42
- * right there, matching the reuse-then-`Jolt.destroy()`-once pattern
43
- * in Jolt's own `soft-body-creator.js` sample. `bodyCreation`
44
- * (`SoftBodyCreationSettings`) is the same story: `CreateSoftBody`
45
- * copies what it needs, so it's freed right after — same contract as
46
- * `JoltSettings` → `JoltInterface` below.
47
- * - `sharedSettings` itself (`SoftBodySharedSettings`) is different: it
48
- * is REFCOUNTED (`AddRef`/`Release`/`GetRefCount` in the vendored
49
- * typings, like `Shape`) and the body reads it every step
50
- * (`SoftBodyMotionProperties.GetSettings()`) for face/constraint
51
- * topology. Refcounted RefTargets are freed BY JOLT ITSELF when the
52
- * last reference drops (Release of the final ref IS the delete) —
53
- * so it gets NO explicit `Jolt.destroy(...)` at all: destroying
54
- * `bodyCreation` releases the ctor's ref, and `dispose()`'s
55
- * `DestroyBody` releases the body's (last) ref, which deletes it.
56
- * An explicit destroy on top would be a use-after-free (empirically
57
- * confirmed with a `GetRefCount()` probe against real Jolt WASM).
58
- * Same rule for the collider's `Shape`: `destroy(creation)` releases
59
- * the creation-settings ref, `DestroyBody` releases the body's —
60
- * never destroy the shape directly.
61
- * - The preallocated tick-loop temporaries described above (`tmpPos`/
62
- * `tmpVel` in `buildClothGrid`, `tmpPos`/`identityQuat` in
63
- * `buildKinematicCollider`) are plain (non-refcounted) `Vec3`/`RVec3`/
64
- * `Quat` wrappers reused for the object's whole lifetime — freed in that
65
- * object's own `dispose()`.
66
- */
67
- import * as THREE from 'three';
68
- const LAYER_NON_MOVING = 0;
69
- const LAYER_MOVING = 1;
70
- const NUM_OBJECT_LAYERS = 2;
71
- const NUM_BROAD_PHASE_LAYERS = 2;
72
- export function createJoltWorld(jolt, options = {}) {
73
- const gravity = options.gravity ?? { x: 0, y: -9.81, z: 0 };
74
- const collisionSteps = options.collisionSteps ?? 1;
75
- const objectFilter = new jolt.ObjectLayerPairFilterTable(NUM_OBJECT_LAYERS);
76
- objectFilter.EnableCollision(LAYER_MOVING, LAYER_MOVING);
77
- const bpInterface = new jolt.BroadPhaseLayerInterfaceTable(NUM_OBJECT_LAYERS, NUM_BROAD_PHASE_LAYERS);
78
- bpInterface.MapObjectToBroadPhaseLayer(LAYER_NON_MOVING, new jolt.BroadPhaseLayer(LAYER_NON_MOVING));
79
- bpInterface.MapObjectToBroadPhaseLayer(LAYER_MOVING, new jolt.BroadPhaseLayer(LAYER_MOVING));
80
- const settings = new jolt.JoltSettings();
81
- settings.mObjectLayerPairFilter = objectFilter;
82
- settings.mBroadPhaseLayerInterface = bpInterface;
83
- settings.mObjectVsBroadPhaseLayerFilter = new jolt.ObjectVsBroadPhaseLayerFilterTable(bpInterface, NUM_BROAD_PHASE_LAYERS, objectFilter, NUM_OBJECT_LAYERS);
84
- const joltInterface = new jolt.JoltInterface(settings);
85
- jolt.destroy(settings);
86
- const physicsSystem = joltInterface.GetPhysicsSystem();
87
- physicsSystem.SetGravity(new jolt.Vec3(gravity.x, gravity.y, gravity.z));
88
- const bodyInterface = physicsSystem.GetBodyInterface();
89
- return {
90
- jolt,
91
- joltInterface,
92
- physicsSystem,
93
- bodyInterface,
94
- movingLayer: LAYER_MOVING,
95
- step(dt) {
96
- joltInterface.Step(dt, collisionSteps);
97
- },
98
- dispose() {
99
- jolt.destroy(joltInterface);
100
- },
101
- };
102
- }
103
- export function buildKinematicCollider(world, shape) {
104
- const { jolt, bodyInterface } = world;
105
- const joltShape = shape.kind === 'sphere'
106
- ? new jolt.SphereShape(shape.radius)
107
- : new jolt.CapsuleShape(shape.halfHeight, shape.radius);
108
- const creation = new jolt.BodyCreationSettings(joltShape, new jolt.RVec3(0, 0, 0), new jolt.Quat(0, 0, 0, 1), jolt.EMotionType_Kinematic, world.movingLayer);
109
- // A per-tick-driven kinematic collider must NEVER sleep: Jolt puts a
110
- // near-zero-velocity kinematic body to sleep after ~0.5 s, and
111
- // `Body.MoveKinematic` (unlike the BodyInterface variant) does NOT wake
112
- // it — after any brief stillness (e.g. a garment-settle warm-up) the
113
- // collider would silently freeze at its old pose FOREVER while the
114
- // character walks away (observed live: the whole cape sailed through the
115
- // torso and every contact-robustness knob was powerless against it).
116
- creation.mAllowSleeping = false;
117
- const body = bodyInterface.CreateBody(creation);
118
- bodyInterface.AddBody(body.GetID(), jolt.EActivation_Activate);
119
- // `CreateBody` copied what it needs — free the one-shot settings struct
120
- // now (same contract as `SoftBodyCreationSettings` in `buildClothGrid`).
121
- // This also releases `creation`'s reference on the REFCOUNTED `joltShape`;
122
- // the body holds the remaining shape ref, so `joltShape` must NOT get a
123
- // `jolt.destroy` anywhere — `DestroyBody` in `dispose()` releases that
124
- // last ref and Jolt deletes the shape itself (see module header).
125
- jolt.destroy(creation);
126
- // Preallocated once, reused every `moveTo` call — see module header.
127
- const tmpPos = new jolt.RVec3(0, 0, 0);
128
- const identityQuat = new jolt.Quat(0, 0, 0, 1);
129
- return {
130
- body,
131
- moveTo(worldPos, dt) {
132
- tmpPos.Set(worldPos.x, worldPos.y, worldPos.z);
133
- body.MoveKinematic(tmpPos, identityQuat, dt);
134
- },
135
- dispose() {
136
- bodyInterface.RemoveBody(body.GetID());
137
- bodyInterface.DestroyBody(body.GetID());
138
- jolt.destroy(tmpPos);
139
- jolt.destroy(identityQuat);
140
- },
141
- };
142
- }
143
- /** Build the `SoftBodySharedSettings` (vertex grid + face list + edge/shear/
144
- * bend constraints) for a `cols`x`rows` cloth. Split out of `buildClothGrid`
145
- * purely to keep that function's complexity down — not reused elsewhere. */
146
- function buildSoftBodySharedSettings(jolt, options, pins, idx) {
147
- const { cols, rows } = options;
148
- const vertexMassKg = options.vertexMassKg ?? 0.02;
149
- const pinSet = new Set(pins.map((p) => idx(p.row, p.col)));
150
- const sharedSettings = new jolt.SoftBodySharedSettings();
151
- const vertices = sharedSettings.mVertices;
152
- for (let row = 0; row < rows; row++) {
153
- for (let col = 0; col < cols; col++) {
154
- const p = options.restPosition(row, col);
155
- const v = new jolt.SoftBodySharedSettingsVertex();
156
- const pos = new jolt.Float3(p.x, p.y, p.z);
157
- v.mPosition = pos;
158
- v.mInvMass = pinSet.has(idx(row, col)) ? 0 : 1 / vertexMassKg;
159
- vertices.push_back(v);
160
- // `push_back` (like the property-setter assignment above it) copies
161
- // BY VALUE into `sharedSettings`'s own storage — Jolt's own
162
- // `soft-body-creator.js` sample reuses/destroys a single `v` the same
163
- // way across its whole grid loop — so both temporaries are safe to
164
- // free the instant the copy has happened.
165
- jolt.destroy(pos);
166
- jolt.destroy(v);
167
- }
168
- }
169
- sharedSettings.mVertices = vertices;
170
- const faces = sharedSettings.mFaces;
171
- for (let row = 0; row < rows - 1; row++) {
172
- for (let col = 0; col < cols - 1; col++) {
173
- const faceA = new jolt.SoftBodySharedSettingsFace(idx(row, col), idx(row + 1, col), idx(row, col + 1), 0);
174
- faces.push_back(faceA);
175
- jolt.destroy(faceA);
176
- const faceB = new jolt.SoftBodySharedSettingsFace(idx(row, col + 1), idx(row + 1, col), idx(row + 1, col + 1), 0);
177
- faces.push_back(faceB);
178
- jolt.destroy(faceB);
179
- }
180
- }
181
- sharedSettings.mFaces = faces;
182
- const vertexAttr = new jolt.SoftBodySharedSettingsVertexAttributes();
183
- vertexAttr.mCompliance = options.compliance ?? 0.0002;
184
- vertexAttr.mShearCompliance = options.shearCompliance ?? 0.0002;
185
- vertexAttr.mBendCompliance = options.bendCompliance ?? 0.002;
186
- const vertexAttrArr = new jolt.ArraySoftBodySharedSettingsVertexAttributes();
187
- vertexAttrArr.push_back(vertexAttr);
188
- // Same value-copy-then-free story as above: `CreateConstraints` below
189
- // reads from `vertexAttrArr`'s OWN backing copy (via `.data()`), not this
190
- // original wrapper, so it's safe to free right after the push_back.
191
- jolt.destroy(vertexAttr);
192
- sharedSettings.CreateConstraints(vertexAttrArr.data(), vertexAttrArr.size(), jolt.SoftBodySharedSettings_EBendType_Distance);
193
- sharedSettings.Optimize();
194
- jolt.destroy(vertexAttrArr);
195
- return sharedSettings;
196
- }
197
- /** Build the renderable (non-skinned) mesh: a plain `BufferGeometry` whose
198
- * `position` attribute `ClothGrid.tick` overwrites every frame. */
199
- function buildClothMesh(scene, options, idx) {
200
- const { cols, rows } = options;
201
- const geometry = new THREE.BufferGeometry();
202
- const positionAttr = new THREE.BufferAttribute(new Float32Array(rows * cols * 3), 3);
203
- positionAttr.setUsage(THREE.DynamicDrawUsage);
204
- geometry.setAttribute('position', positionAttr);
205
- const indices = [];
206
- for (let row = 0; row < rows - 1; row++) {
207
- for (let col = 0; col < cols - 1; col++) {
208
- indices.push(idx(row, col), idx(row + 1, col), idx(row, col + 1));
209
- indices.push(idx(row, col + 1), idx(row + 1, col), idx(row + 1, col + 1));
210
- }
211
- }
212
- geometry.setIndex(indices);
213
- const material = new THREE.MeshStandardMaterial({
214
- color: options.color ?? 0x7a2f3a,
215
- roughness: 0.85,
216
- side: options.doubleSided === false ? THREE.FrontSide : THREE.DoubleSide,
217
- });
218
- const mesh = new THREE.Mesh(geometry, material);
219
- mesh.castShadow = true;
220
- mesh.frustumCulled = false;
221
- scene.add(mesh);
222
- return { mesh, geometry, positionAttr, material };
223
- }
224
- export function buildClothGrid(world, scene, options) {
225
- const { jolt, bodyInterface } = world;
226
- const { cols, rows } = options;
227
- const pins = options.pins ?? Array.from({ length: cols }, (_, col) => ({ row: 0, col }));
228
- const idx = (row, col) => row * cols + col;
229
- const sharedSettings = buildSoftBodySharedSettings(jolt, options, pins, idx);
230
- const bodyCreation = new jolt.SoftBodyCreationSettings(sharedSettings, new jolt.RVec3(0, 0, 0), new jolt.Quat(0, 0, 0, 1), world.movingLayer);
231
- bodyCreation.mNumIterations = options.numIterations ?? 4;
232
- if (options.vertexRadius !== undefined)
233
- bodyCreation.mVertexRadius = options.vertexRadius;
234
- if (options.linearDamping !== undefined)
235
- bodyCreation.mLinearDamping = options.linearDamping;
236
- bodyCreation.mPressure = 0;
237
- bodyCreation.mGravityFactor = options.gravityFactor ?? 1;
238
- bodyCreation.mFacesDoubleSided = true;
239
- bodyCreation.mUpdatePosition = false;
240
- // Kinematically-pinned cloth must never sleep either: `tick()` drives the
241
- // pins by writing `SoftBodyVertex.mPosition/.mVelocity` DIRECTLY, which
242
- // does not count as activity — a cape that settles still for ~0.5 s would
243
- // sleep and stay frozen while its pins walk away.
244
- bodyCreation.mAllowSleeping = false;
245
- const clothBody = bodyInterface.CreateSoftBody(bodyCreation);
246
- bodyInterface.AddBody(clothBody.GetID(), jolt.EActivation_Activate);
247
- // `CreateSoftBody` copies what it needs out of `bodyCreation` into the
248
- // body's own storage (same "settings object is a one-shot constructor
249
- // argument" contract as `JoltSettings` → `JoltInterface` above) — safe to
250
- // free right away, same as that pattern. `bodyCreation` itself is a plain
251
- // (non-refcounted) settings struct, unlike `sharedSettings` below: freeing
252
- // it here still correctly releases bodyCreation's OWN internal reference
253
- // to `sharedSettings` (which the body has, by now, separately taken its
254
- // own reference to via `CreateSoftBody`).
255
- jolt.destroy(bodyCreation);
256
- // `Body` only exposes the base `GetMotionProperties()`; soft bodies need
257
- // the downcast to reach `GetVertex`/`GetVertices`.
258
- const motionProperties = jolt.castObject(clothBody.GetMotionProperties(), jolt.SoftBodyMotionProperties);
259
- const { mesh, geometry, positionAttr, material } = buildClothMesh(scene, options, idx);
260
- // Preallocated tick-loop temporaries — see module header.
261
- const tmpPos = new jolt.Vec3(0, 0, 0);
262
- const tmpVel = new jolt.Vec3(0, 0, 0);
263
- const prevPinWorld = pins.map((p) => options.restPosition(p.row, p.col));
264
- return {
265
- cols,
266
- rows,
267
- vertexCount: rows * cols,
268
- pins,
269
- mesh,
270
- geometry,
271
- tick(dt, pinTargets) {
272
- for (let i = 0; i < pins.length; i++) {
273
- const target = pinTargets[i];
274
- if (!target)
275
- continue;
276
- const pin = pins[i];
277
- const prev = prevPinWorld[i];
278
- const vertex = motionProperties.GetVertex(idx(pin.row, pin.col));
279
- tmpPos.Set(target.x, target.y, target.z);
280
- vertex.mPosition = tmpPos;
281
- if (dt > 0) {
282
- tmpVel.Set((target.x - prev.x) / dt, (target.y - prev.y) / dt, (target.z - prev.z) / dt);
283
- }
284
- else {
285
- tmpVel.Set(0, 0, 0);
286
- }
287
- vertex.mVelocity = tmpVel;
288
- prev.copy(target);
289
- }
290
- world.step(dt);
291
- const posArr = positionAttr.array;
292
- for (let i = 0; i < rows * cols; i++) {
293
- const v = motionProperties.GetVertex(i);
294
- const p = v.mPosition;
295
- posArr[i * 3] = p.GetX();
296
- posArr[i * 3 + 1] = p.GetY();
297
- posArr[i * 3 + 2] = p.GetZ();
298
- }
299
- positionAttr.needsUpdate = true;
300
- geometry.computeVertexNormals();
301
- },
302
- samplePoints(out = []) {
303
- const n = rows * cols;
304
- out.length = n;
305
- for (let i = 0; i < n; i++) {
306
- const v = motionProperties.GetVertex(i);
307
- const p = v.mPosition;
308
- if (!out[i])
309
- out[i] = new THREE.Vector3();
310
- out[i].set(p.GetX(), p.GetY(), p.GetZ());
311
- }
312
- return out;
313
- },
314
- dispose() {
315
- bodyInterface.RemoveBody(clothBody.GetID());
316
- // NO explicit `jolt.destroy(sharedSettings)` — anywhere. It is a
317
- // refcounted RefTarget that Jolt frees ITSELF when its last reference
318
- // drops, and in Jolt's RefTarget::Release releasing the last ref IS
319
- // the delete. Refcount chain, probed live against real Jolt WASM via
320
- // `GetRefCount()`: 0 after `new` → 1 after the
321
- // `SoftBodyCreationSettings` ctor took its ref → 2 after
322
- // `CreateSoftBody` (the body's own ref) → back to 1 after the
323
- // construction-time `destroy(bodyCreation)` → `DestroyBody` below
324
- // releases that last (body) reference and thereby deletes it. Any
325
- // `destroy(sharedSettings)` after this line would be a use-after-free.
326
- bodyInterface.DestroyBody(clothBody.GetID());
327
- jolt.destroy(tmpPos);
328
- jolt.destroy(tmpVel);
329
- scene.remove(mesh);
330
- geometry.dispose();
331
- material.dispose();
332
- },
333
- };
334
- }
@@ -1,135 +0,0 @@
1
- /**
2
- * Character primitive — spring-bone chains (hair, ponytails, cloth strips)
3
- * on top of `@pixiv/three-vrm-springbone`'s raw API.
4
- *
5
- * This is a THIN COMPOSITION HELPER, not a wrapper (CLAUDE.md "use libraries
6
- * directly"): every export here is a small function that assembles the
7
- * library's own objects (`THREE.Bone`, `VRMSpringBoneJoint`,
8
- * `VRMSpringBoneCollider`, `VRMSpringBoneManager`) — nothing from the
9
- * library is re-exported, and callers still import `@pixiv/three-vrm-
10
- * springbone` types directly for anything beyond what's here. Kept
11
- * deliberately bare: composing a specific character (a caped viking, a
12
- * ponytailed ranger) is ordinary calling code on top of these pieces, not a
13
- * costume/preset system in the engine.
14
- *
15
- * Sharp edge this module exists partly to contain (see the mission brief /
16
- * `cloth-hair-bench/spring-rig.ts`'s header for the full discovery):
17
- * `VRMSpringBoneCollider` overrides `updateWorldMatrix` (the ON-DEMAND,
18
- * manually-invoked method), NOT `updateMatrixWorld` (the one the renderer
19
- * calls automatically) — `SpringColliderRig.reposition()` below calls
20
- * `collider.updateWorldMatrix(true, false)` itself every tick so callers
21
- * can't forget it.
22
- */
23
- import { VRMSpringBoneCollider, type VRMSpringBoneColliderGroup, VRMSpringBoneJoint, VRMSpringBoneManager } from '@pixiv/three-vrm-springbone';
24
- import * as THREE from 'three';
25
- export interface BoneChain {
26
- /** Swinging bones, root (nearest the anchor) first. */
27
- bones: THREE.Bone[];
28
- /** A non-simulated leaf `Object3D` past the last bone — the spring joint
29
- * "tail" target for the last bone in the chain. */
30
- tip: THREE.Object3D;
31
- }
32
- /** World-space offset from `parent`'s CURRENT world position -> the local
33
- * position a new direct child of `parent` must have to sit there. Requires
34
- * `parent.matrixWorld` to be current. Sidesteps ever reasoning about a
35
- * bone's local rest-axis convention (arbitrary per-bone on an imported
36
- * rig) — the caller only ever thinks in world-space directions. */
37
- export declare function worldOffsetToLocalPos(parent: THREE.Object3D, worldDir: THREE.Vector3, length: number): THREE.Vector3;
38
- /** Build a straight chain of `count` new `THREE.Bone`s under `parent`, each
39
- * offset `segmentLength` further along the WORLD-space unit vector
40
- * `worldDir` — the natural rest shape for hair/cloth hanging under gravity.
41
- * Ends with a `tip` `Object3D` (one more segment past the last bone) so
42
- * every bone has an explicit spring-joint child target. Can be anchored to
43
- * either an existing rig bone (hair off a head) or any plain `Object3D`. */
44
- export declare function buildBoneChain(parent: THREE.Object3D, namePrefix: string, count: number, segmentLength: number, worldDir: THREE.Vector3): BoneChain;
45
- export interface ChainJointSettings {
46
- stiffness?: number;
47
- gravityPower?: number;
48
- gravityDir?: THREE.Vector3;
49
- dragForce?: number;
50
- hitRadius?: number;
51
- }
52
- export interface ChainJointHandle {
53
- joints: VRMSpringBoneJoint[];
54
- /** Deregisters every joint this chain added from `manager`. Does NOT
55
- * detach the bones from the scene graph (the caller owns that). */
56
- dispose(): void;
57
- }
58
- /** Register one `VRMSpringBoneJoint` per bone in `chain` on `manager` (each
59
- * targeting the next bone, the last targeting `chain.tip`). Does not call
60
- * `manager.setInitState()` — batch that once after all chains for a
61
- * manager are registered and the scene's world matrices are current (sharp
62
- * edge: `VRMSpringBoneJoint` sets `bone.matrixAutoUpdate = false`, so
63
- * `setInitState()` must run AFTER `scene.updateMatrixWorld(true)`). */
64
- export declare function registerChainJoints(manager: VRMSpringBoneManager, chain: BoneChain, colliderGroups: VRMSpringBoneColliderGroup[], settings?: ChainJointSettings): ChainJointHandle;
65
- export interface SphereColliderDef {
66
- shape: 'sphere';
67
- name: string;
68
- /** The collider tracks this object's world position every `reposition()`. */
69
- followBone: THREE.Object3D;
70
- radius: number;
71
- /** Extra WORLD-space offset added after sampling `followBone`'s position
72
- * (e.g. nudging a head collider up from the neck joint). */
73
- worldOffset?: THREE.Vector3;
74
- }
75
- export interface CapsuleColliderDef {
76
- shape: 'capsule';
77
- name: string;
78
- followBone: THREE.Object3D;
79
- radius: number;
80
- /** Capsule tail, in the collider's own local space (world-axis-aligned —
81
- * colliders are parented directly to the scene, see `buildSpringColliderRig`). */
82
- tail: THREE.Vector3;
83
- worldOffset?: THREE.Vector3;
84
- }
85
- export type ColliderDef = SphereColliderDef | CapsuleColliderDef;
86
- export interface SpringColliderRig {
87
- group: VRMSpringBoneColliderGroup;
88
- colliders: Map<string, VRMSpringBoneCollider>;
89
- /** Reposition every collider from its `followBone`'s CURRENT world
90
- * transform and refresh its `colliderMatrix` (see module header). Call
91
- * once per tick, BEFORE `manager.update(dt)`. */
92
- reposition(): void;
93
- dispose(): void;
94
- }
95
- /** Build sphere/capsule colliders parented directly to `scene` (world
96
- * space) — sidesteps reasoning about any bone's local rest-axis convention
97
- * for the collider shape's offset/tail vectors. */
98
- export declare function buildSpringColliderRig(scene: THREE.Scene, defs: ColliderDef[]): SpringColliderRig;
99
- export interface SpringChainRigOptions {
100
- parent: THREE.Object3D;
101
- namePrefix: string;
102
- count: number;
103
- segmentLength: number;
104
- worldDir: THREE.Vector3;
105
- /** Colliders this chain collides against. Omit for a chain with no
106
- * collision (e.g. a side strand tucked away from the body). */
107
- colliderRig?: SpringColliderRig;
108
- settings?: ChainJointSettings;
109
- }
110
- export interface SpringChainRig {
111
- bones: THREE.Bone[];
112
- tip: THREE.Object3D;
113
- /** The manager owning this chain's joints — a "manager-compatible handle"
114
- * a caller can also register additional joints on directly. */
115
- manager: VRMSpringBoneManager;
116
- /** Repositions `colliderRig` (if given) and steps the spring simulation.
117
- * Handles the collider `updateWorldMatrix` footgun internally — callers
118
- * never need to call `collider.updateWorldMatrix` themselves. */
119
- tick(dt: number): void;
120
- dispose(): void;
121
- }
122
- /** Compose `buildBoneChain` + `registerChainJoints` behind one call for the
123
- * common single-chain case: builds the chain, gives it its OWN
124
- * `VRMSpringBoneManager` (managers are cheap — one per independent chain
125
- * keeps `dispose()`/`tick()` fully self-contained), registers its joints,
126
- * and calls `setInitState()` once construction is complete.
127
- *
128
- * For MULTIPLE chains sharing one collider rig (e.g. a ponytail + two side
129
- * strands all colliding against the same head), build each chain with its
130
- * own `buildSpringChainRig` call (same `colliderRig` passed to each) and
131
- * tick all of them — `colliderRig.reposition()` is idempotent per frame, so
132
- * calling it once per chain tick is correct, just slightly redundant work
133
- * (cheap: it only touches a handful of colliders). */
134
- export declare function buildSpringChainRig(options: SpringChainRigOptions): SpringChainRig;
135
- //# sourceMappingURL=spring-chain.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"spring-chain.d.ts","sourceRoot":"","sources":["../../src/character/spring-chain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EACL,qBAAqB,EACrB,KAAK,0BAA0B,EAG/B,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B,MAAM,WAAW,SAAS;IACxB,uDAAuD;IACvD,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;IACpB;wDACoD;IACpD,GAAG,EAAE,KAAK,CAAC,QAAQ,CAAC;CACrB;AAED;;;;oEAIoE;AACpE,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,KAAK,CAAC,QAAQ,EACtB,QAAQ,EAAE,KAAK,CAAC,OAAO,EACvB,MAAM,EAAE,MAAM,GACb,KAAK,CAAC,OAAO,CAKf;AAED;;;;;6EAK6E;AAC7E,wBAAgB,cAAc,CAC5B,MAAM,EAAE,KAAK,CAAC,QAAQ,EACtB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,KAAK,CAAC,OAAO,GACtB,SAAS,CAmBX;AAMD,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B;wEACoE;IACpE,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;wEAKwE;AACxE,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,oBAAoB,EAC7B,KAAK,EAAE,SAAS,EAChB,cAAc,EAAE,0BAA0B,EAAE,EAC5C,QAAQ,GAAE,kBAAuB,GAChC,gBAAgB,CA0BlB;AAMD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,QAAQ,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf;iEAC6D;IAC7D,WAAW,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf;uFACmF;IACnF,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC;CAC7B;AAED,MAAM,MAAM,WAAW,GAAG,iBAAiB,GAAG,kBAAkB,CAAC;AAEjE,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,0BAA0B,CAAC;IAClC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IAC9C;;sDAEkD;IAClD,UAAU,IAAI,IAAI,CAAC;IACnB,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;oDAEoD;AACpD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,iBAAiB,CA0CjG;AAMD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC;IACxB;oEACgE;IAChE,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;IACpB,GAAG,EAAE,KAAK,CAAC,QAAQ,CAAC;IACpB;oEACgE;IAChE,OAAO,EAAE,oBAAoB,CAAC;IAC9B;;sEAEkE;IAClE,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;;;;;;;uDAWuD;AACvD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,qBAAqB,GAAG,cAAc,CA0BlF"}
@@ -1,165 +0,0 @@
1
- /**
2
- * Character primitive — spring-bone chains (hair, ponytails, cloth strips)
3
- * on top of `@pixiv/three-vrm-springbone`'s raw API.
4
- *
5
- * This is a THIN COMPOSITION HELPER, not a wrapper (CLAUDE.md "use libraries
6
- * directly"): every export here is a small function that assembles the
7
- * library's own objects (`THREE.Bone`, `VRMSpringBoneJoint`,
8
- * `VRMSpringBoneCollider`, `VRMSpringBoneManager`) — nothing from the
9
- * library is re-exported, and callers still import `@pixiv/three-vrm-
10
- * springbone` types directly for anything beyond what's here. Kept
11
- * deliberately bare: composing a specific character (a caped viking, a
12
- * ponytailed ranger) is ordinary calling code on top of these pieces, not a
13
- * costume/preset system in the engine.
14
- *
15
- * Sharp edge this module exists partly to contain (see the mission brief /
16
- * `cloth-hair-bench/spring-rig.ts`'s header for the full discovery):
17
- * `VRMSpringBoneCollider` overrides `updateWorldMatrix` (the ON-DEMAND,
18
- * manually-invoked method), NOT `updateMatrixWorld` (the one the renderer
19
- * calls automatically) — `SpringColliderRig.reposition()` below calls
20
- * `collider.updateWorldMatrix(true, false)` itself every tick so callers
21
- * can't forget it.
22
- */
23
- import { VRMSpringBoneCollider, VRMSpringBoneColliderShapeCapsule, VRMSpringBoneColliderShapeSphere, VRMSpringBoneJoint, VRMSpringBoneManager, } from '@pixiv/three-vrm-springbone';
24
- import * as THREE from 'three';
25
- const DEFAULT_GRAVITY_DIR = new THREE.Vector3(0, -1, 0);
26
- /** World-space offset from `parent`'s CURRENT world position -> the local
27
- * position a new direct child of `parent` must have to sit there. Requires
28
- * `parent.matrixWorld` to be current. Sidesteps ever reasoning about a
29
- * bone's local rest-axis convention (arbitrary per-bone on an imported
30
- * rig) — the caller only ever thinks in world-space directions. */
31
- export function worldOffsetToLocalPos(parent, worldDir, length) {
32
- const parentWorld = new THREE.Vector3();
33
- parent.getWorldPosition(parentWorld);
34
- const targetWorld = parentWorld.clone().addScaledVector(worldDir, length);
35
- return parent.worldToLocal(targetWorld.clone());
36
- }
37
- /** Build a straight chain of `count` new `THREE.Bone`s under `parent`, each
38
- * offset `segmentLength` further along the WORLD-space unit vector
39
- * `worldDir` — the natural rest shape for hair/cloth hanging under gravity.
40
- * Ends with a `tip` `Object3D` (one more segment past the last bone) so
41
- * every bone has an explicit spring-joint child target. Can be anchored to
42
- * either an existing rig bone (hair off a head) or any plain `Object3D`. */
43
- export function buildBoneChain(parent, namePrefix, count, segmentLength, worldDir) {
44
- const bones = [];
45
- let cur = parent;
46
- cur.updateWorldMatrix(true, false);
47
- for (let i = 0; i < count; i++) {
48
- const localPos = worldOffsetToLocalPos(cur, worldDir, segmentLength);
49
- const bone = new THREE.Bone();
50
- bone.name = `${namePrefix}${i}`;
51
- bone.position.copy(localPos);
52
- cur.add(bone);
53
- bone.updateWorldMatrix(true, false);
54
- bones.push(bone);
55
- cur = bone;
56
- }
57
- const tip = new THREE.Object3D();
58
- tip.name = `${namePrefix}Tip`;
59
- tip.position.copy(worldOffsetToLocalPos(cur, worldDir, segmentLength));
60
- cur.add(tip);
61
- return { bones, tip };
62
- }
63
- /** Register one `VRMSpringBoneJoint` per bone in `chain` on `manager` (each
64
- * targeting the next bone, the last targeting `chain.tip`). Does not call
65
- * `manager.setInitState()` — batch that once after all chains for a
66
- * manager are registered and the scene's world matrices are current (sharp
67
- * edge: `VRMSpringBoneJoint` sets `bone.matrixAutoUpdate = false`, so
68
- * `setInitState()` must run AFTER `scene.updateMatrixWorld(true)`). */
69
- export function registerChainJoints(manager, chain, colliderGroups, settings = {}) {
70
- const joints = [];
71
- for (let i = 0; i < chain.bones.length; i++) {
72
- const bone = chain.bones[i];
73
- const child = chain.bones[i + 1] ?? chain.tip;
74
- const joint = new VRMSpringBoneJoint(bone, child, {
75
- stiffness: settings.stiffness ?? 1.2,
76
- gravityPower: settings.gravityPower ?? 0.9,
77
- gravityDir: settings.gravityDir ?? DEFAULT_GRAVITY_DIR,
78
- dragForce: settings.dragForce ?? 0.35,
79
- hitRadius: settings.hitRadius ?? 0.02,
80
- }, colliderGroups);
81
- manager.addJoint(joint);
82
- joints.push(joint);
83
- }
84
- return {
85
- joints,
86
- dispose() {
87
- for (const joint of joints)
88
- manager.deleteJoint(joint);
89
- },
90
- };
91
- }
92
- /** Build sphere/capsule colliders parented directly to `scene` (world
93
- * space) — sidesteps reasoning about any bone's local rest-axis convention
94
- * for the collider shape's offset/tail vectors. */
95
- export function buildSpringColliderRig(scene, defs) {
96
- const colliders = new Map();
97
- const followers = [];
98
- for (const def of defs) {
99
- const collider = def.shape === 'sphere'
100
- ? new VRMSpringBoneCollider(new VRMSpringBoneColliderShapeSphere({ radius: def.radius }))
101
- : new VRMSpringBoneCollider(new VRMSpringBoneColliderShapeCapsule({
102
- radius: def.radius,
103
- offset: new THREE.Vector3(0, 0, 0),
104
- tail: def.tail,
105
- }));
106
- scene.add(collider);
107
- colliders.set(def.name, collider);
108
- followers.push({ def, collider });
109
- }
110
- const group = {
111
- name: 'body',
112
- colliders: [...colliders.values()],
113
- };
114
- const worldTmp = new THREE.Vector3();
115
- return {
116
- group,
117
- colliders,
118
- reposition() {
119
- for (const { def, collider } of followers) {
120
- def.followBone.getWorldPosition(worldTmp);
121
- collider.position.copy(worldTmp);
122
- if (def.worldOffset)
123
- collider.position.add(def.worldOffset);
124
- collider.updateWorldMatrix(true, false);
125
- }
126
- },
127
- dispose() {
128
- for (const collider of colliders.values())
129
- scene.remove(collider);
130
- colliders.clear();
131
- },
132
- };
133
- }
134
- /** Compose `buildBoneChain` + `registerChainJoints` behind one call for the
135
- * common single-chain case: builds the chain, gives it its OWN
136
- * `VRMSpringBoneManager` (managers are cheap — one per independent chain
137
- * keeps `dispose()`/`tick()` fully self-contained), registers its joints,
138
- * and calls `setInitState()` once construction is complete.
139
- *
140
- * For MULTIPLE chains sharing one collider rig (e.g. a ponytail + two side
141
- * strands all colliding against the same head), build each chain with its
142
- * own `buildSpringChainRig` call (same `colliderRig` passed to each) and
143
- * tick all of them — `colliderRig.reposition()` is idempotent per frame, so
144
- * calling it once per chain tick is correct, just slightly redundant work
145
- * (cheap: it only touches a handful of colliders). */
146
- export function buildSpringChainRig(options) {
147
- const chain = buildBoneChain(options.parent, options.namePrefix, options.count, options.segmentLength, options.worldDir);
148
- const manager = new VRMSpringBoneManager();
149
- const colliderGroups = options.colliderRig ? [options.colliderRig.group] : [];
150
- const jointHandle = registerChainJoints(manager, chain, colliderGroups, options.settings);
151
- manager.setInitState();
152
- return {
153
- bones: chain.bones,
154
- tip: chain.tip,
155
- manager,
156
- tick(dt) {
157
- options.colliderRig?.reposition();
158
- manager.update(dt);
159
- },
160
- dispose() {
161
- jointHandle.dispose();
162
- chain.bones[0]?.removeFromParent();
163
- },
164
- };
165
- }