@cavegiant/cave-world-r3f 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (339) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/LICENSE +21 -0
  3. package/README.md +189 -0
  4. package/dist/core/connector-label/readiness.d.ts +11 -0
  5. package/dist/core/connector-label/readiness.d.ts.map +1 -0
  6. package/dist/core/connector-label/readiness.js +31 -0
  7. package/dist/core/connector-label/readiness.js.map +1 -0
  8. package/dist/core/connector-label/types.d.ts +64 -0
  9. package/dist/core/connector-label/types.d.ts.map +1 -0
  10. package/dist/core/connector-label/types.js +47 -0
  11. package/dist/core/connector-label/types.js.map +1 -0
  12. package/dist/core/context/cave-world-context.d.ts +96 -0
  13. package/dist/core/context/cave-world-context.d.ts.map +1 -0
  14. package/dist/core/context/cave-world-context.js +100 -0
  15. package/dist/core/context/cave-world-context.js.map +1 -0
  16. package/dist/core/errors.d.ts +34 -0
  17. package/dist/core/errors.d.ts.map +1 -0
  18. package/dist/core/errors.js +17 -0
  19. package/dist/core/errors.js.map +1 -0
  20. package/dist/core/events/event-bus.d.ts +122 -0
  21. package/dist/core/events/event-bus.d.ts.map +1 -0
  22. package/dist/core/events/event-bus.js +62 -0
  23. package/dist/core/events/event-bus.js.map +1 -0
  24. package/dist/core/hooks/use-cave-event.d.ts +13 -0
  25. package/dist/core/hooks/use-cave-event.d.ts.map +1 -0
  26. package/dist/core/hooks/use-cave-event.js +12 -0
  27. package/dist/core/hooks/use-cave-event.js.map +1 -0
  28. package/dist/core/i18n/messages.d.ts +82 -0
  29. package/dist/core/i18n/messages.d.ts.map +1 -0
  30. package/dist/core/i18n/messages.js +131 -0
  31. package/dist/core/i18n/messages.js.map +1 -0
  32. package/dist/core/index.d.ts +11 -0
  33. package/dist/core/index.d.ts.map +1 -0
  34. package/dist/core/index.js +47 -0
  35. package/dist/core/index.js.map +1 -0
  36. package/dist/core/logging/logger.d.ts +29 -0
  37. package/dist/core/logging/logger.d.ts.map +1 -0
  38. package/dist/core/logging/logger.js +47 -0
  39. package/dist/core/logging/logger.js.map +1 -0
  40. package/dist/core/registry/component-registry.d.ts +41 -0
  41. package/dist/core/registry/component-registry.d.ts.map +1 -0
  42. package/dist/core/registry/component-registry.js +34 -0
  43. package/dist/core/registry/component-registry.js.map +1 -0
  44. package/dist/core/registry/object-registry.d.ts +38 -0
  45. package/dist/core/registry/object-registry.d.ts.map +1 -0
  46. package/dist/core/registry/object-registry.js +32 -0
  47. package/dist/core/registry/object-registry.js.map +1 -0
  48. package/dist/explore/cave-explore.d.ts +85 -0
  49. package/dist/explore/cave-explore.d.ts.map +1 -0
  50. package/dist/explore/cave-explore.js +204 -0
  51. package/dist/explore/cave-explore.js.map +1 -0
  52. package/dist/explore/cave-orbit-viewer.d.ts +76 -0
  53. package/dist/explore/cave-orbit-viewer.d.ts.map +1 -0
  54. package/dist/explore/cave-orbit-viewer.js +123 -0
  55. package/dist/explore/cave-orbit-viewer.js.map +1 -0
  56. package/dist/explore/characters/character-configs.d.ts +38 -0
  57. package/dist/explore/characters/character-configs.d.ts.map +1 -0
  58. package/dist/explore/characters/character-configs.js +45 -0
  59. package/dist/explore/characters/character-configs.js.map +1 -0
  60. package/dist/explore/characters/character-controls.d.ts +44 -0
  61. package/dist/explore/characters/character-controls.d.ts.map +1 -0
  62. package/dist/explore/characters/character-pose.d.ts +19 -0
  63. package/dist/explore/characters/character-pose.d.ts.map +1 -0
  64. package/dist/explore/characters/character-pose.js +13 -0
  65. package/dist/explore/characters/character-pose.js.map +1 -0
  66. package/dist/explore/characters/local-character-model.d.ts +53 -0
  67. package/dist/explore/characters/local-character-model.d.ts.map +1 -0
  68. package/dist/explore/characters/local-character-model.js +36 -0
  69. package/dist/explore/characters/local-character-model.js.map +1 -0
  70. package/dist/explore/characters/mixamo-style-bone-map.d.ts +9 -0
  71. package/dist/explore/characters/mixamo-style-bone-map.d.ts.map +1 -0
  72. package/dist/explore/characters/mixamo-style-bone-map.js +28 -0
  73. package/dist/explore/characters/mixamo-style-bone-map.js.map +1 -0
  74. package/dist/explore/characters/remote-character-controller.d.ts +38 -0
  75. package/dist/explore/characters/remote-character-controller.d.ts.map +1 -0
  76. package/dist/explore/characters/remote-character-controller.js +135 -0
  77. package/dist/explore/characters/remote-character-controller.js.map +1 -0
  78. package/dist/explore/characters/remote-character.d.ts +19 -0
  79. package/dist/explore/characters/remote-character.d.ts.map +1 -0
  80. package/dist/explore/characters/remote-character.js +63 -0
  81. package/dist/explore/characters/remote-character.js.map +1 -0
  82. package/dist/explore/connected-spaces-renderer.d.ts +16 -0
  83. package/dist/explore/connected-spaces-renderer.d.ts.map +1 -0
  84. package/dist/explore/connected-spaces-renderer.js +103 -0
  85. package/dist/explore/connected-spaces-renderer.js.map +1 -0
  86. package/dist/explore/hooks/use-action-shortcuts.d.ts +16 -0
  87. package/dist/explore/hooks/use-action-shortcuts.d.ts.map +1 -0
  88. package/dist/explore/hooks/use-action-shortcuts.js +23 -0
  89. package/dist/explore/hooks/use-action-shortcuts.js.map +1 -0
  90. package/dist/explore/hooks/use-active-space-notify.d.ts +11 -0
  91. package/dist/explore/hooks/use-active-space-notify.d.ts.map +1 -0
  92. package/dist/explore/hooks/use-active-space-notify.js +17 -0
  93. package/dist/explore/hooks/use-active-space-notify.js.map +1 -0
  94. package/dist/explore/hooks/use-character-sync.d.ts +46 -0
  95. package/dist/explore/hooks/use-character-sync.d.ts.map +1 -0
  96. package/dist/explore/hooks/use-character-sync.js +72 -0
  97. package/dist/explore/hooks/use-character-sync.js.map +1 -0
  98. package/dist/explore/hooks/use-connector-preloader.d.ts +20 -0
  99. package/dist/explore/hooks/use-connector-preloader.d.ts.map +1 -0
  100. package/dist/explore/hooks/use-connector-preloader.js +78 -0
  101. package/dist/explore/hooks/use-connector-preloader.js.map +1 -0
  102. package/dist/explore/hooks/use-connector-transitions.d.ts +31 -0
  103. package/dist/explore/hooks/use-connector-transitions.d.ts.map +1 -0
  104. package/dist/explore/hooks/use-connector-transitions.js +63 -0
  105. package/dist/explore/hooks/use-connector-transitions.js.map +1 -0
  106. package/dist/explore/hooks/use-explore-actions.d.ts +17 -0
  107. package/dist/explore/hooks/use-explore-actions.d.ts.map +1 -0
  108. package/dist/explore/hooks/use-explore-actions.js +134 -0
  109. package/dist/explore/hooks/use-explore-actions.js.map +1 -0
  110. package/dist/explore/hooks/use-load-error-notify.d.ts +11 -0
  111. package/dist/explore/hooks/use-load-error-notify.d.ts.map +1 -0
  112. package/dist/explore/hooks/use-load-error-notify.js +18 -0
  113. package/dist/explore/hooks/use-load-error-notify.js.map +1 -0
  114. package/dist/explore/hooks/use-primary-space-loader.d.ts +24 -0
  115. package/dist/explore/hooks/use-primary-space-loader.d.ts.map +1 -0
  116. package/dist/explore/hooks/use-primary-space-loader.js +29 -0
  117. package/dist/explore/hooks/use-primary-space-loader.js.map +1 -0
  118. package/dist/explore/index.d.ts +37 -0
  119. package/dist/explore/index.d.ts.map +1 -0
  120. package/dist/explore/index.js +107 -0
  121. package/dist/explore/index.js.map +1 -0
  122. package/dist/explore/loaders/cave-loader.d.ts +58 -0
  123. package/dist/explore/loaders/cave-loader.d.ts.map +1 -0
  124. package/dist/explore/loaders/cave-loader.js +79 -0
  125. package/dist/explore/loaders/cave-loader.js.map +1 -0
  126. package/dist/explore/math/space-transforms.d.ts +49 -0
  127. package/dist/explore/math/space-transforms.d.ts.map +1 -0
  128. package/dist/explore/math/space-transforms.js +54 -0
  129. package/dist/explore/math/space-transforms.js.map +1 -0
  130. package/dist/explore/overlays/action-bubble.d.ts +8 -0
  131. package/dist/explore/overlays/action-bubble.d.ts.map +1 -0
  132. package/dist/explore/overlays/action-bubble.js +18 -0
  133. package/dist/explore/overlays/action-bubble.js.map +1 -0
  134. package/dist/explore/overlays/action-panel.d.ts +12 -0
  135. package/dist/explore/overlays/action-panel.d.ts.map +1 -0
  136. package/dist/explore/overlays/action-panel.js +69 -0
  137. package/dist/explore/overlays/action-panel.js.map +1 -0
  138. package/dist/explore/overlays/connector-label-beacon.d.ts +11 -0
  139. package/dist/explore/overlays/connector-label-beacon.d.ts.map +1 -0
  140. package/dist/explore/overlays/connector-label-beacon.js +38 -0
  141. package/dist/explore/overlays/connector-label-beacon.js.map +1 -0
  142. package/dist/explore/overlays/connector-label-tag-shell.d.ts +16 -0
  143. package/dist/explore/overlays/connector-label-tag-shell.d.ts.map +1 -0
  144. package/dist/explore/overlays/connector-label-tag-shell.js +18 -0
  145. package/dist/explore/overlays/connector-label-tag-shell.js.map +1 -0
  146. package/dist/explore/overlays/detail-window.d.ts +9 -0
  147. package/dist/explore/overlays/detail-window.d.ts.map +1 -0
  148. package/dist/explore/overlays/detail-window.js +92 -0
  149. package/dist/explore/overlays/detail-window.js.map +1 -0
  150. package/dist/explore/overlays/explore-helper.d.ts +44 -0
  151. package/dist/explore/overlays/explore-helper.d.ts.map +1 -0
  152. package/dist/explore/overlays/explore-helper.js +57 -0
  153. package/dist/explore/overlays/explore-helper.js.map +1 -0
  154. package/dist/explore/overlays/icons.d.ts +16 -0
  155. package/dist/explore/overlays/icons.d.ts.map +1 -0
  156. package/dist/explore/overlays/icons.js +34 -0
  157. package/dist/explore/overlays/icons.js.map +1 -0
  158. package/dist/explore/overlays/space-load-error-overlay.d.ts +27 -0
  159. package/dist/explore/overlays/space-load-error-overlay.d.ts.map +1 -0
  160. package/dist/explore/overlays/space-load-error-overlay.js +24 -0
  161. package/dist/explore/overlays/space-load-error-overlay.js.map +1 -0
  162. package/dist/explore/services/websocket.service.d.ts +180 -0
  163. package/dist/explore/services/websocket.service.d.ts.map +1 -0
  164. package/dist/explore/services/websocket.service.js +187 -0
  165. package/dist/explore/services/websocket.service.js.map +1 -0
  166. package/dist/explore/simple-character.d.ts +46 -0
  167. package/dist/explore/simple-character.d.ts.map +1 -0
  168. package/dist/explore/simple-character.js +119 -0
  169. package/dist/explore/simple-character.js.map +1 -0
  170. package/dist/explore/stores/action-prompt.store.d.ts +27 -0
  171. package/dist/explore/stores/action-prompt.store.d.ts.map +1 -0
  172. package/dist/explore/stores/action-prompt.store.js +14 -0
  173. package/dist/explore/stores/action-prompt.store.js.map +1 -0
  174. package/dist/explore/stores/cave-explore.store.d.ts +77 -0
  175. package/dist/explore/stores/cave-explore.store.d.ts.map +1 -0
  176. package/dist/explore/stores/cave-explore.store.js +66 -0
  177. package/dist/explore/stores/cave-explore.store.js.map +1 -0
  178. package/dist/explore/stores/explore-context.d.ts +35 -0
  179. package/dist/explore/stores/explore-context.d.ts.map +1 -0
  180. package/dist/explore/stores/explore-context.js +43 -0
  181. package/dist/explore/stores/explore-context.js.map +1 -0
  182. package/dist/explore/styles/cave-world-css.d.ts +10 -0
  183. package/dist/explore/styles/cave-world-css.d.ts.map +1 -0
  184. package/dist/explore/styles/cave-world-css.js +935 -0
  185. package/dist/explore/styles/cave-world-css.js.map +1 -0
  186. package/dist/explore/styles/inject.d.ts +32 -0
  187. package/dist/explore/styles/inject.d.ts.map +1 -0
  188. package/dist/explore/styles/inject.js +40 -0
  189. package/dist/explore/styles/inject.js.map +1 -0
  190. package/dist/explore/utils/schedule-idle.d.ts +12 -0
  191. package/dist/explore/utils/schedule-idle.d.ts.map +1 -0
  192. package/dist/explore/utils/schedule-idle.js +16 -0
  193. package/dist/explore/utils/schedule-idle.js.map +1 -0
  194. package/dist/explore/viewer-shared.d.ts +56 -0
  195. package/dist/explore/viewer-shared.d.ts.map +1 -0
  196. package/dist/index.d.ts +16 -0
  197. package/dist/index.d.ts.map +1 -0
  198. package/dist/index.js +78 -0
  199. package/dist/index.js.map +1 -0
  200. package/dist/space/cave-base-layer.d.ts +42 -0
  201. package/dist/space/cave-base-layer.d.ts.map +1 -0
  202. package/dist/space/cave-base-layer.js +221 -0
  203. package/dist/space/cave-base-layer.js.map +1 -0
  204. package/dist/space/cave-custom-layer.d.ts +12 -0
  205. package/dist/space/cave-custom-layer.d.ts.map +1 -0
  206. package/dist/space/cave-custom-layer.js +17 -0
  207. package/dist/space/cave-custom-layer.js.map +1 -0
  208. package/dist/space/cave-env.d.ts +6 -0
  209. package/dist/space/cave-env.d.ts.map +1 -0
  210. package/dist/space/cave-env.js +23 -0
  211. package/dist/space/cave-env.js.map +1 -0
  212. package/dist/space/cave-space.d.ts +46 -0
  213. package/dist/space/cave-space.d.ts.map +1 -0
  214. package/dist/space/cave-space.js +37 -0
  215. package/dist/space/cave-space.js.map +1 -0
  216. package/dist/space/connector-label-host.d.ts +21 -0
  217. package/dist/space/connector-label-host.d.ts.map +1 -0
  218. package/dist/space/connector-label-host.js +65 -0
  219. package/dist/space/connector-label-host.js.map +1 -0
  220. package/dist/space/index.d.ts +18 -0
  221. package/dist/space/index.d.ts.map +1 -0
  222. package/dist/space/index.js +47 -0
  223. package/dist/space/index.js.map +1 -0
  224. package/dist/space/objects/builtin-registrar.d.ts +17 -0
  225. package/dist/space/objects/builtin-registrar.d.ts.map +1 -0
  226. package/dist/space/objects/builtin-registrar.js +19 -0
  227. package/dist/space/objects/builtin-registrar.js.map +1 -0
  228. package/dist/space/objects/custom-object.d.ts +9 -0
  229. package/dist/space/objects/custom-object.d.ts.map +1 -0
  230. package/dist/space/objects/custom-object.js +56 -0
  231. package/dist/space/objects/custom-object.js.map +1 -0
  232. package/dist/space/objects/image-object.d.ts +7 -0
  233. package/dist/space/objects/image-object.d.ts.map +1 -0
  234. package/dist/space/objects/image-object.js +14 -0
  235. package/dist/space/objects/image-object.js.map +1 -0
  236. package/dist/space/objects/model-object/fbx-object.d.ts +8 -0
  237. package/dist/space/objects/model-object/fbx-object.d.ts.map +1 -0
  238. package/dist/space/objects/model-object/fbx-object.js +26 -0
  239. package/dist/space/objects/model-object/fbx-object.js.map +1 -0
  240. package/dist/space/objects/model-object/gltf-object.d.ts +9 -0
  241. package/dist/space/objects/model-object/gltf-object.d.ts.map +1 -0
  242. package/dist/space/objects/model-object/gltf-object.js +66 -0
  243. package/dist/space/objects/model-object/gltf-object.js.map +1 -0
  244. package/dist/space/objects/model-object/index.d.ts +9 -0
  245. package/dist/space/objects/model-object/index.d.ts.map +1 -0
  246. package/dist/space/objects/model-object/index.js +12 -0
  247. package/dist/space/objects/model-object/index.js.map +1 -0
  248. package/dist/space/objects/model-object/splat-object.d.ts +9 -0
  249. package/dist/space/objects/model-object/splat-object.d.ts.map +1 -0
  250. package/dist/space/objects/model-object/splat-object.js +19 -0
  251. package/dist/space/objects/model-object/splat-object.js.map +1 -0
  252. package/dist/space/objects/object-components/windows/index.d.ts +5 -0
  253. package/dist/space/objects/object-components/windows/index.d.ts.map +1 -0
  254. package/dist/space/objects/object-components/windows/index.js +20 -0
  255. package/dist/space/objects/object-components/windows/index.js.map +1 -0
  256. package/dist/space/objects/placeholder-object.d.ts +7 -0
  257. package/dist/space/objects/placeholder-object.d.ts.map +1 -0
  258. package/dist/space/objects/placeholder-object.js +12 -0
  259. package/dist/space/objects/placeholder-object.js.map +1 -0
  260. package/dist/space/objects/poi-object.d.ts +7 -0
  261. package/dist/space/objects/poi-object.d.ts.map +1 -0
  262. package/dist/space/objects/poi-object.js +38 -0
  263. package/dist/space/objects/poi-object.js.map +1 -0
  264. package/dist/space/objects/portal-object.d.ts +7 -0
  265. package/dist/space/objects/portal-object.d.ts.map +1 -0
  266. package/dist/space/objects/portal-object.js +84 -0
  267. package/dist/space/objects/portal-object.js.map +1 -0
  268. package/dist/space/objects/video-object.d.ts +7 -0
  269. package/dist/space/objects/video-object.d.ts.map +1 -0
  270. package/dist/space/objects/video-object.js +32 -0
  271. package/dist/space/objects/video-object.js.map +1 -0
  272. package/dist/space/polygon-boundary.d.ts +10 -0
  273. package/dist/space/polygon-boundary.d.ts.map +1 -0
  274. package/dist/space/polygon-boundary.js +205 -0
  275. package/dist/space/polygon-boundary.js.map +1 -0
  276. package/dist/space/splats/spark/robust-splat-mesh.d.ts +59 -0
  277. package/dist/space/splats/spark/robust-splat-mesh.d.ts.map +1 -0
  278. package/dist/space/splats/spark/robust-splat-mesh.js +105 -0
  279. package/dist/space/splats/spark/robust-splat-mesh.js.map +1 -0
  280. package/dist/space/splats/spark/splat-mesh.d.ts +5 -0
  281. package/dist/space/splats/spark/splat-mesh.d.ts.map +1 -0
  282. package/dist/space/splats/spark/splat-mesh.js +7 -0
  283. package/dist/space/splats/spark/splat-mesh.js.map +1 -0
  284. package/dist/space/splats/spark/splat-spread-reveal.d.ts +14 -0
  285. package/dist/space/splats/spark/splat-spread-reveal.d.ts.map +1 -0
  286. package/dist/space/splats/spark/splat-spread-reveal.js +45 -0
  287. package/dist/space/splats/spark/splat-spread-reveal.js.map +1 -0
  288. package/dist/space/utils/cave-world-player.d.ts +3 -0
  289. package/dist/space/utils/cave-world-player.d.ts.map +1 -0
  290. package/dist/space/utils/cave-world-player.js +5 -0
  291. package/dist/space/utils/cave-world-player.js.map +1 -0
  292. package/dist/space/utils/configure-canvas.d.ts +20 -0
  293. package/dist/space/utils/configure-canvas.d.ts.map +1 -0
  294. package/dist/space/utils/configure-canvas.js +12 -0
  295. package/dist/space/utils/configure-canvas.js.map +1 -0
  296. package/dist/space/utils/polygon-boundary-geometry.d.ts +8 -0
  297. package/dist/space/utils/polygon-boundary-geometry.d.ts.map +1 -0
  298. package/dist/space/utils/polygon-boundary-geometry.js +20 -0
  299. package/dist/space/utils/polygon-boundary-geometry.js.map +1 -0
  300. package/dist/space/utils/polygon-boundary-segments.d.ts +50 -0
  301. package/dist/space/utils/polygon-boundary-segments.d.ts.map +1 -0
  302. package/dist/space/utils/polygon-boundary-segments.js +64 -0
  303. package/dist/space/utils/polygon-boundary-segments.js.map +1 -0
  304. package/dist/space/utils/rotation-compat.d.ts +4 -0
  305. package/dist/space/utils/rotation-compat.d.ts.map +1 -0
  306. package/dist/space/utils/rotation-compat.js +9 -0
  307. package/dist/space/utils/rotation-compat.js.map +1 -0
  308. package/dist/space/utils/select-splat-level.d.ts +52 -0
  309. package/dist/space/utils/select-splat-level.d.ts.map +1 -0
  310. package/dist/space/utils/select-splat-level.js +43 -0
  311. package/dist/space/utils/select-splat-level.js.map +1 -0
  312. package/dist/space/utils/spark-performance.d.ts +10 -0
  313. package/dist/space/utils/spark-performance.d.ts.map +1 -0
  314. package/dist/space/utils/spark-performance.js +10 -0
  315. package/dist/space/utils/spark-performance.js.map +1 -0
  316. package/dist/space/utils/splat-collider-helper.d.ts +5 -0
  317. package/dist/space/utils/splat-collider-helper.d.ts.map +1 -0
  318. package/dist/space/utils/splat-collider-helper.js +162 -0
  319. package/dist/space/utils/splat-collider-helper.js.map +1 -0
  320. package/dist/space/utils/touch-primary-device.d.ts +16 -0
  321. package/dist/space/utils/touch-primary-device.d.ts.map +1 -0
  322. package/dist/space/utils/touch-primary-device.js +52 -0
  323. package/dist/space/utils/touch-primary-device.js.map +1 -0
  324. package/dist/space/utils/use-visibility-frameloop.d.ts +20 -0
  325. package/dist/space/utils/use-visibility-frameloop.d.ts.map +1 -0
  326. package/dist/space/utils/use-visibility-frameloop.js +18 -0
  327. package/dist/space/utils/use-visibility-frameloop.js.map +1 -0
  328. package/dist/styles.css +930 -0
  329. package/dist/types/index.d.ts +2 -0
  330. package/dist/types/index.d.ts.map +1 -0
  331. package/dist/types/index.js +2 -0
  332. package/dist/types/index.js.map +1 -0
  333. package/dist/types/space-types.d.ts +404 -0
  334. package/dist/types/space-types.d.ts.map +1 -0
  335. package/doc/API.md +617 -0
  336. package/doc/ARCHITECTURE.md +264 -0
  337. package/doc/multiplayer-protocol.md +757 -0
  338. package/doc/scene-json-structure.md +567 -0
  339. package/package.json +131 -0
@@ -0,0 +1,567 @@
1
+ # 空间场景 JSON 结构设计文档
2
+
3
+ ## 概述
4
+
5
+ 本文档描述 `@cavegiant/cave-world-r3f` 所消费的 3D 场景 JSON(`CaveSpace`)数据结构。该设计参考 Unity 的 GameObject + Component 模式,提供了高扩展性的场景描述能力。
6
+
7
+ 完整 TypeScript 定义见 `@cavegiant/cave-world-r3f/types`,该子路径为纯类型、零运行时。
8
+
9
+ > **关于「宿主注册类型」**:部分 `type`(`infoPoint`、`panoramaVideo`、`digitalHuman2D`、`text`、`light`、`audio`、`npc`)是**官方 schema 类型但没有内置渲染器** —— 它们的视觉与交互高度依赖具体产品。SDK 只保证类型契约;未注册渲染器时这类对象会被静默跳过,注册方式见 [API.md](./API.md#object-renderers)。
10
+
11
+ ## 核心设计理念
12
+
13
+ 1. **GameObject + Component 模式**: 每个 3D 对象都是一个 GameObject,通过添加不同的 Component 来实现各种功能
14
+ 2. **高扩展性**: 支持自定义 Component 类型,便于后续功能扩展
15
+ 3. **层次化结构**: 支持父子关系,便于场景组织
16
+ 4. **类型安全**: 提供完整的 TypeScript 类型定义
17
+
18
+ ## JSON 结构
19
+
20
+ ### 1. 空间场景根结构 (Space)
21
+
22
+ ```json
23
+ {
24
+ "specVersion": "1.0.0", // JSON结构规范版本
25
+ "contentVersion": 3, // 数据内容版本(发布时自增)
26
+ "metadata": {
27
+ "name": "场景名称",
28
+ "description": "场景描述",
29
+ "creatorId": "3123123123123",
30
+ "publishTime": 1759949369151,
31
+ "thumbnail": "场景缩略图URL"
32
+ },
33
+ "baseLayer": {
34
+ "visible": true,
35
+ "transform": {
36
+ "position": [0, 0, 0],
37
+ "rotation": [0, 0, 0, 1],
38
+ "scale": [1, 1, 1]
39
+ },
40
+ "scene": {
41
+ // 基础场景
42
+ "type": "splat", // "splat" | "model"
43
+ "url": "基础场景资源URL(默认 LOD,单档场景必填;splatLevels 存在时作为兜底)",
44
+ "splatCount": 3500000, // 可选,3DGS 点数(仅供作者参考;超出设备能力时控制台会警告)
45
+ "splatLevels": [
46
+ // 可选,多 LOD 列表。存在时系统按设备能力(PC ≈ 3M,移动端 ≈ 2M)挑选合适档位。
47
+ { "url": "low.splat", "splatCount": 800000 },
48
+ { "url": "medium.splat", "splatCount": 1800000 },
49
+ { "url": "high.splat", "splatCount": 3000000 }
50
+ ]
51
+ },
52
+ "colliders": [
53
+ // 场景碰撞体
54
+ {
55
+ "id": "123",
56
+ "type": "box", // "box" | "gltf" | "model"
57
+ "box": {
58
+ "position": [0, 0, 0],
59
+ "rotation": [0, 0, 0, 1],
60
+ "scale": [1, 1, 1]
61
+ }
62
+ },
63
+ {
64
+ "id": "456",
65
+ "type": "gltf",
66
+ "src": "https://xxxxx.glb"
67
+ },
68
+ {
69
+ "id": "789",
70
+ "type": "model",
71
+ "url": "https://xxxxx.obj",
72
+ "size": 6042883 // 可选,文件大小(字节)
73
+ }
74
+ ],
75
+ "boundaries": [
76
+ // 基础边界(随transform同步变换)
77
+ {
78
+ "id": "123",
79
+ "type": "box", // "box" | "polygon"
80
+ "collisionEnabled": true,
81
+ "box": {
82
+ "position": [0, 0, 0],
83
+ "rotation": [0, 0, 0, 1],
84
+ "scale": [1, 1, 1]
85
+ }
86
+ },
87
+ {
88
+ "id": "456",
89
+ "type": "polygon",
90
+ "collisionEnabled": true,
91
+ "polygon": {
92
+ "points": [
93
+ [10, 0, 10],
94
+ [30, 0, 10],
95
+ [30, 0, 30],
96
+ [10, 0, 30]
97
+ ],
98
+ "height": 5
99
+ }
100
+ }
101
+ ],
102
+ "lighting": {
103
+ "ambientColor": "#404040",
104
+ "ambientIntensity": 0.3,
105
+ "directionalLight": {
106
+ "color": "#ffffff",
107
+ "intensity": 1.0,
108
+ "direction": [1, -1, 0],
109
+ "castShadow": true
110
+ }
111
+ },
112
+ "skybox": {
113
+ // 天空盒/背景
114
+ "type": "cubemap", // "cubemap" | "color"
115
+ "color": "#87CEEB",
116
+ "urls": {
117
+ "px": "right.jpg",
118
+ "nx": "left.jpg",
119
+ "py": "top.jpg",
120
+ "ny": "bottom.jpg",
121
+ "pz": "front.jpg",
122
+ "nz": "back.jpg"
123
+ }
124
+ },
125
+ "ambientAudio": {
126
+ // 背景环境音
127
+ "url": "环境音URL",
128
+ "volume": 0.5,
129
+ "autoplay": true
130
+ },
131
+ "connectors": [
132
+ // 场景连接器——触发场景过渡
133
+ {
134
+ "id": "conn-1",
135
+ "name": "通往大厅",
136
+ "type": "connector",
137
+ "transform": {
138
+ "position": [10, 0, 0],
139
+ "rotation": [0, 1.57, 0], // Euler 角度
140
+ "scale": [2, 3, 1]
141
+ },
142
+ "connectorInfo": {
143
+ "to": [
144
+ {
145
+ "caveWorldId": "target-space-id",
146
+ "transitionType": "seamless", // "seamless" | "portal"
147
+ "transform": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 5, 0, 3, 1] // Matrix4x4 列主序,方向:源 → 目标(seamless 专用)
148
+ }
149
+ ]
150
+ }
151
+ },
152
+ {
153
+ "id": "conn-2",
154
+ "name": "传送门",
155
+ "type": "connector",
156
+ "transform": {
157
+ "position": [-5, 0, 8],
158
+ "rotation": [0, 0, 0],
159
+ "scale": [2, 3, 2]
160
+ },
161
+ "connectorInfo": {
162
+ "to": [
163
+ {
164
+ "caveWorldId": "lobby-space-id",
165
+ "transitionType": "portal",
166
+ "connectorId": "lobby-conn-1" // 目标场景中的连接器 ID(portal 专用)
167
+ },
168
+ {
169
+ "caveWorldId": "garden-space-id",
170
+ "transitionType": "portal",
171
+ "connectorId": "garden-conn-1"
172
+ }
173
+ ]
174
+ }
175
+ }
176
+ ],
177
+ "physics": {
178
+ "enabled": true,
179
+ "gravity": [0, -9.81, 0]
180
+ },
181
+ "spawnPoint": {
182
+ "position": [0, 0, 0],
183
+ "yaw": 0
184
+ }
185
+ },
186
+ "customLayers": [
187
+ // 自定义图层数组(默认一个)
188
+ {
189
+ "name": "default",
190
+ "visible": true,
191
+ "objects": []
192
+ }
193
+ ]
194
+ }
195
+ ```
196
+
197
+ #### baseLayer.scene 字段说明(3DGS LOD)
198
+
199
+ | 字段 | 类型 | 必填 | 说明 |
200
+ | ------------- | ---------------------------- | ---- | ---------------------------------------------------------------- |
201
+ | `type` | `'splat' \| 'model'` | 是 | 基础场景资源类型 |
202
+ | `url` | `string` | 是 | 默认资源 URL;当 `splatLevels` 不存在时被直接使用 |
203
+ | `source` | `{ from, id? }` | 否 | 资源来源元信息(业务侧使用) |
204
+ | `splatCount` | `number` | 否 | 默认 URL 的 3DGS 点数。仅作为提示:超出设备阈值时会在控制台 warn |
205
+ | `splatLevels` | `Array<{ url, splatCount }>` | 否 | 多档 LOD 列表。存在时系统按设备能力自动选档 |
206
+
207
+ **LOD 选择规则**(仅当 `splatLevels` 非空时启用):
208
+
209
+ 1. 计算当前设备的点数上限 `cap`:
210
+ - 桌面:3,000,000(≈300 万)
211
+ - 移动端(通过 `(hover: none) and (pointer: coarse)` 检测):2,000,000(≈200 万)
212
+ 2. 在 `splatCount ≤ cap` 的档位里挑 **点数最多** 的(最佳画质 + 流畅)。
213
+ 3. 如果所有档位都超过 `cap`,挑 **点数最少** 的(兜底:降低画质但仍可播放)。
214
+ 4. 如果 `splatLevels` 为空数组或所有 entry 无 `url`,退化回 `url` 字段。
215
+
216
+ 设备阈值在 `@cave-world/space` 中以 `DESKTOP_SPLAT_COUNT_CAP` / `MOBILE_SPLAT_COUNT_CAP` 常量导出。
217
+
218
+ #### baseLayer.spawnPoint 字段说明(出生点)
219
+
220
+ | 字段 | 类型 | 必填 | 说明 |
221
+ | ---------- | --------- | ---- | --------------------------------------------------------------------------------------------- |
222
+ | `position` | `Vector3` | 是 | 出生位置,baseLayer 局部坐标(应用 `baseLayer.transform` 之前,与 collider / connector 一致) |
223
+ | `yaw` | `number` | 是 | 人物朝向,绕 Y 轴的弧度。`0` 表示面向 +Z |
224
+
225
+ **运行时行为**:
226
+
227
+ - 仅在玩家**首次进入主场景**且 `space:initialized` 触发后应用一次。
228
+ - 世界位姿由 `G_target × T_target × spawn_local` 计算(与 portal 连接器落点同一套矩阵管线)。
229
+ - seamless / portal 场景切换不会重新应用;缺省时保留 `<SimpleCharacter>` 默认初始位姿。
230
+
231
+ ### 2. 要素结构 (CustomObject)
232
+
233
+ 内置渲染器覆盖 `model`、`splat`、`image`、`video`、`poi`、`portal`、`placeholder`;其余为宿主注册类型(见文首说明)。
234
+
235
+ ```json
236
+ {
237
+ "id": "unique-element-id",
238
+ "name": "要素名称",
239
+ "type": "model", // "splat" | "model" | "text" | "image" | "video" | "npc" | "light" | "audio" | "placeholder" | "poi" | "digitalHuman2D" | "portal" | "infoPoint" | "panoramaVideo"
240
+ "visible": true,
241
+ "transform": {
242
+ "position": [0, 0, 0],
243
+ "rotation": [0, 0, 0, 1], // quaternion [x, y, z, w]
244
+ "scale": [1, 1, 1]
245
+ },
246
+ "parent": "parent-element-id", // 可选,父要素ID
247
+ "children": ["child-id-1", "child-id-2"], // 可选,子要素ID数组
248
+
249
+ // 根据type不同,包含不同的主要属性
250
+ "model": {
251
+ "url": "模型文件URL",
252
+ "color": "#ffffff", // 可选,整体颜色
253
+ "opacity": 1.0, // 可选,透明度
254
+ "castShadow": true,
255
+ "receiveShadow": true
256
+ },
257
+
258
+ "text": {
259
+ "content": "显示的文字内容",
260
+ "fontSize": 16,
261
+ "color": "#ffffff",
262
+ "backgroundColor": "#000000", // 可选
263
+ "maxWidth": 200, // 可选
264
+ "alignment": "center" // "left" | "center" | "right"
265
+ },
266
+
267
+ "image": {
268
+ "url": "图片URL",
269
+ "opacity": 0.5, // 可选
270
+ "transparent": true, // 可选
271
+ "billboard": true // 可选,是否始终面向相机
272
+ },
273
+
274
+ "video": {
275
+ "url": "视频URL",
276
+ "autoplay": false,
277
+ "loop": true,
278
+ "muted": false,
279
+ "controls": true
280
+ },
281
+
282
+ "light": {
283
+ "lightType": "directional", // "directional" | "point" | "spot"
284
+ "color": "#ffffff",
285
+ "intensity": 1.0,
286
+ "range": 10.0, // point/spot light
287
+ "spotAngle": 30.0, // spot light
288
+ "castShadow": true
289
+ },
290
+
291
+ "audio": {
292
+ "url": "音频文件URL",
293
+ "volume": 1.0,
294
+ "loop": false,
295
+ "autoplay": false,
296
+ "spatial": true // 是否3D空间音频
297
+ },
298
+
299
+ // 自定义行为组件
300
+ "components": {
301
+ "Window": {
302
+ "name": "Window",
303
+ "type": "leftRight",
304
+ "content": []
305
+ },
306
+ "Collider": {
307
+ "name": "Collider",
308
+ "shape": "box", // "box" | "sphere" | "mesh"
309
+ "transform": {
310
+ "position": [0, 0, 0],
311
+ "rotation": [0, 0, 0, 1], // quaternion [x, y, z, w]
312
+ "scale": [1, 1, 1]
313
+ },
314
+ "isTrigger": false
315
+ }
316
+ }
317
+ }
318
+ ```
319
+
320
+ #### infoPoint 信息点(`type: "infoPoint"`)
321
+
322
+ 结构化信息标注:3D 场景中的可点击标签 + 详情载荷。SDK 仅定义 JSON 契约;**运行时渲染与详情 UI 由宿主门户注册**(`ObjectRegistry.register('infoPoint', Renderer)`),与 `text` / `npc` 等同。
323
+
324
+ **与 `poi` 的区别**:`poi` 使用 `text` 字段渲染 3D 文本圆点;`infoPoint` 使用 `infoPoint.detail` 结构化载荷,标签样式与弹窗由门户实现。
325
+
326
+ **与 `Window` 组件的区别**:`Window` 为 proximity + F 键打开 SDK `DetailWindow`;`infoPoint` 为点击 Html 标签触发 `object:click`,详情由门户监听并渲染。
327
+
328
+ **`label` vs `detail.title`**:`infoPoint.label` 为 3D 标签文案(缺省回退 `name`);`detail.title` 为详情面板 badge 文案(如 gallery 布局顶部徽章)。
329
+
330
+ | 字段 | 类型 | 必填 | 说明 |
331
+ | ------------------------------------ | ----------------- | ---- | -------------- |
332
+ | `type` | `'infoPoint'` | 是 | 要素类型 |
333
+ | `id`, `name`, `visible`, `transform` | 同 CustomObject | 是 | 标准要素字段 |
334
+ | `infoPoint` | `InfoPointProps` | 是 | 信息点载荷 |
335
+ | `infoPoint.label` | `string` | 否 | 3D 标签文字 |
336
+ | `infoPoint.detail` | `InfoPointDetail` | 是 | 点击后详情数据 |
337
+ | `infoPoint.detail.variant` | `string` | 是 | 详情布局类型 |
338
+
339
+ **gallery variant**(`detail.variant === "gallery"`):
340
+
341
+ | 字段 | 类型 | 必填 | 说明 |
342
+ | --------- | ---------- | ---- | -------------------------- |
343
+ | `images` | `string[]` | 是 | 图片 URL 列表(至少 1 张) |
344
+ | `title` | `string` | 是 | 详情面板 badge 文案 |
345
+ | `content` | `string` | 是 | 正文(支持 `\n` 换行) |
346
+
347
+ **variant 扩展**:新增 variant 时在本文档登记字段 schema;门户通过 `detail.variant` 分发渲染,SDK 不内置 UI。
348
+
349
+ ```json
350
+ {
351
+ "id": "info-grassland-01",
352
+ "name": "草原介绍点",
353
+ "type": "infoPoint",
354
+ "visible": true,
355
+ "transform": {
356
+ "position": [0, 1.8, -3],
357
+ "rotation": [0, 0, 0, 1],
358
+ "scale": [1, 1, 1]
359
+ },
360
+ "infoPoint": {
361
+ "label": "草原介绍点",
362
+ "detail": {
363
+ "variant": "gallery",
364
+ "images": ["https://cdn.example.com/a.jpg", "https://cdn.example.com/b.jpg"],
365
+ "title": "介绍",
366
+ "content": "正文内容,支持换行。\n\n第二段。"
367
+ }
368
+ }
369
+ }
370
+ ```
371
+
372
+ #### panoramaVideo 360° 全景视频(`type: "panoramaVideo"`)
373
+
374
+ 可点击的 360° 全景视频热点:3D 场景中的视频标签 + 全屏沉浸式播放器。SDK 仅定义 JSON 契约;**运行时标签与播放器由宿主门户注册**(`ObjectRegistry.register('panoramaVideo', Renderer)`)。
375
+
376
+ **与 `video` 的区别**:`video` 在场景内以平面贴图 inline 播放;`panoramaVideo` 为 Html 标签点击后打开全屏 equirectangular 球面播放器。
377
+
378
+ **与 `infoPoint` 的区别**:`infoPoint` 为信息展示(gallery 等底部弹窗);`panoramaVideo` 为沉浸式媒体热点,标签样式与全屏播放器独立实现。
379
+
380
+ | 字段 | 类型 | 必填 | 说明 |
381
+ | ------------------------------------ | -------------------- | ---- | ------------------------------ |
382
+ | `type` | `'panoramaVideo'` | 是 | 要素类型 |
383
+ | `id`, `name`, `visible`, `transform` | 同 CustomObject | 是 | 标准要素字段 |
384
+ | `panoramaVideo` | `PanoramaVideoProps` | 是 | 全景视频载荷 |
385
+ | `panoramaVideo.label` | `string` | 否 | 3D 标签文字(缺省回退 `name`) |
386
+ | `panoramaVideo.url` | `string` | 是 | 等距柱状投影(2:1)视频 URL |
387
+ | `panoramaVideo.poster` | `string` | 否 | 加载前封面图 |
388
+ | `panoramaVideo.title` | `string` | 否 | 播放器内标题 overlay |
389
+ | `panoramaVideo.description` | `string` | 否 | 播放器内说明 overlay |
390
+ | `panoramaVideo.autoplay` | `boolean` | 否 | 打开后自动播放,默认 `true` |
391
+ | `panoramaVideo.loop` | `boolean` | 否 | 循环播放,默认 `false` |
392
+ | `panoramaVideo.muted` | `boolean` | 否 | 静音,默认 `true` |
393
+ | `panoramaVideo.initialYaw` | `number` | 否 | 初始水平视角(度),默认 `0` |
394
+ | `panoramaVideo.initialPitch` | `number` | 否 | 初始俯仰角(度),默认 `0` |
395
+ | `panoramaVideo.fov` | `number` | 否 | 视场角(度),默认 `75` |
396
+
397
+ ```json
398
+ {
399
+ "id": "panorama-sunset-01",
400
+ "name": "日落全景",
401
+ "type": "panoramaVideo",
402
+ "visible": true,
403
+ "transform": {
404
+ "position": [2.5, 1.8, -4.0],
405
+ "rotation": [0, 0, 0, 1],
406
+ "scale": [1, 1, 1]
407
+ },
408
+ "panoramaVideo": {
409
+ "label": "观看日落全景",
410
+ "url": "https://cdn.example.com/panorama/sunset-360.mp4",
411
+ "poster": "https://cdn.example.com/panorama/sunset-poster.jpg",
412
+ "title": "草原日落",
413
+ "description": "拖动屏幕环视,感受鄂尔多斯草原的黄昏。",
414
+ "autoplay": true,
415
+ "loop": false,
416
+ "muted": true,
417
+ "initialYaw": 90,
418
+ "initialPitch": 0,
419
+ "fov": 75
420
+ }
421
+ }
422
+ ```
423
+
424
+ ### 3. 自定义图层结构 (CustomLayer)
425
+
426
+ ```json
427
+ {
428
+ "name": "图层名称",
429
+ "visible": true,
430
+ "objects": [
431
+ // 要素数组
432
+ ]
433
+ }
434
+ ```
435
+
436
+ ### 4. Component 类型
437
+
438
+ 功能性/特征类组件:
439
+ ComponentName: ComponentAttribute
440
+
441
+ #### Window - 窗口
442
+
443
+ ```json
444
+ {
445
+ "placement": "leftRight",
446
+ "content": []
447
+ }
448
+ ```
449
+
450
+ #### Collider - 碰撞体
451
+
452
+ ```json
453
+ {
454
+ "shape": "box", // "box" | "sphere" | "mesh"
455
+ "transform": {
456
+ "position": [0, 0, 0],
457
+ "rotation": [0, 0, 0, 1], // quaternion [x, y, z, w]
458
+ "scale": [1, 1, 1]
459
+ },
460
+ "isTrigger": false
461
+ }
462
+ ```
463
+
464
+ #### Rigidbody - 刚体
465
+
466
+ ```json
467
+ {
468
+ "mass": 1.0,
469
+ "useGravity": true,
470
+ "isKinematic": false
471
+ }
472
+ ```
473
+
474
+ ### 5. 连接器结构 (ConnectorDef)
475
+
476
+ 连接器定义在 `baseLayer.connectors` 数组中,用于描述场景之间的过渡关系。每个连接器的几何体为一个 box,当用户角色触碰到该 box 时触发场景过渡。
477
+
478
+ ```json
479
+ {
480
+ "id": "conn-1",
481
+ "name": "连接器名称",
482
+ "type": "connector",
483
+ "transform": {
484
+ "position": [10, 0, 0],
485
+ "rotation": [0, 1.57, 0],
486
+ "scale": [2, 3, 1]
487
+ },
488
+ "connectorInfo": {
489
+ "to": [
490
+ {
491
+ "caveWorldId": "目标场景ID",
492
+ "transitionType": "seamless",
493
+ "transform": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 5, 0, 3, 1]
494
+ }
495
+ ]
496
+ },
497
+ "label": {
498
+ "variant": "beacon",
499
+ "text": "古庙遗址",
500
+ "thumbnail": "https://cdn/.../thumb.webp",
501
+ "visibility": { "maxDistance": 50 }
502
+ }
503
+ }
504
+ ```
505
+
506
+ #### label 字段(可选)
507
+
508
+ 始终可见的 3D 指引标签,仅对含 `portal` 目标的 connector 生效。
509
+
510
+ | 字段 | 类型 | 说明 |
511
+ | ------------------------------ | ---------------------------- | ---------------------------------------------------------------------- |
512
+ | `label` | `ConnectorLabelDef \| false` | 省略时遵循 SDK `connectorLabel` prop;`false` 显式关闭 |
513
+ | `label.variant` | `string` | 内置 `'beacon'`(默认) |
514
+ | `label.text` | `string` | 显示文案;缺省取目标场景 `metadata.name`,再缺省为「前方场景」 |
515
+ | `label.icon` | `string` | 图标 URL |
516
+ | `label.thumbnail` | `string` | 缩略图 URL;缺省取目标场景 `metadata.thumbnail` |
517
+ | `label.anchorOffset` | `[x,y,z]` | 标签锚点相对 connector 中心的偏移;默认 `[0, scaleY/4+0.2, 0]` |
518
+ | `label.visibility.maxDistance` | `number` | 最大可见距离(米),默认 30 |
519
+ | `label.visibility.minDistance` | `number` | 最小可见距离(米),默认 5;进入 box 时 SDK 也会隐藏 |
520
+ | `label.visibility.fadeRange` | `number` | 淡入淡出范围,默认 5 |
521
+ | `label.custom` | `object` | 透传给自定义 `renderConnectorLabel` |
522
+ | `label.clickable` | `boolean` | 点击标签是否触发 portal 跳转,默认 `true`;设为 `false` 时仅展示不可点 |
523
+
524
+ ```json
525
+ {
526
+ "id": "conn-portal",
527
+ "name": "传送门",
528
+ "type": "connector",
529
+ "transform": { "position": [10, 0, 0], "rotation": [0, 1.57, 0], "scale": [2, 3, 1] },
530
+ "connectorInfo": {
531
+ "to": [{ "caveWorldId": "scene-b", "transitionType": "portal", "connectorId": "entry" }]
532
+ }
533
+ }
534
+ ```
535
+
536
+ 纯 seamless connector 即使配置 `label` 也不会显示标签。
537
+
538
+ #### 过渡类型
539
+
540
+ | transitionType | 行为 | 专属字段 |
541
+ | -------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
542
+ | `seamless` | 角色触碰 box 时自动切换:隐藏当前场景,显示目标场景 | `transform`(Matrix4x4 列主序 16 元素数组,**从源场景到目标场景的对齐矩阵**——见下文方向说明) |
543
+ | `portal` | 角色触碰 box 时展示目的地列表,用户选择后传送到目标场景对应连接器位置 | `connectorId`(目标场景中的连接器 ID,决定传送位置和朝向) |
544
+
545
+ #### transform 字段说明
546
+
547
+ - `position`:box 中心在 baseLayer 局部坐标系中的位置 `[x, y, z]`
548
+ - `rotation`:Euler 角度 `[x, y, z]`(注意:与 CustomObject 使用的四元数不同)
549
+ - `scale`:box 尺寸 `[width, height, depth]`
550
+
551
+ #### seamless connectorInfo.to[].transform 方向约定
552
+
553
+ `connectorInfo.to[].transform`(仅 `seamless` 使用)是一个 4x4 列主序矩阵 `M_raw`,
554
+ **方向为「源场景 → 目标场景」**——即把一个点从源场景的模型局部坐标系
555
+ (应用 `baseLayer.transform` 之前的坐标)映射到目标场景对应的模型局部坐标系:
556
+
557
+ ```
558
+ p_target_local = M_raw × p_source_local
559
+ ```
560
+
561
+ 在渲染时,SDK 会基于此约定计算目标场景 `<group>` 的世界变换:
562
+
563
+ ```
564
+ G_target = G_source × T_source × inverse(M_raw) × inverse(T_target)
565
+ ```
566
+
567
+ 其中 `T_source` / `T_target` 是各自 `baseLayer.transform` 对应的矩阵。