three-base 2.0.142 → 2.0.145

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 (227) hide show
  1. package/DirectionalLight.d.ts +6 -6
  2. package/DirectionalLight.js +68 -68
  3. package/EventMap.d.ts +103 -103
  4. package/EventMap.js +17 -17
  5. package/EventMesh.d.ts +18 -18
  6. package/EventMesh.js +59 -59
  7. package/ExtrudeMesh.d.ts +112 -112
  8. package/ExtrudeMesh.js +342 -342
  9. package/FPScontrol.d.ts +511 -511
  10. package/FPScontrol.js +1799 -1799
  11. package/FPScontrol.ts +1855 -1855
  12. package/Fire/Fire.d.ts +28 -28
  13. package/Fire/Fire.js +80 -80
  14. package/Fire/FireGeometry.d.ts +9 -9
  15. package/Fire/FireGeometry.js +40 -40
  16. package/Fire/FireMaterial.d.ts +28 -28
  17. package/Fire/FireMaterial.js +32 -32
  18. package/Fire/index.d.ts +2 -2
  19. package/Fire/index.js +2 -2
  20. package/GLTFDracoLoader.d.ts +71 -71
  21. package/GLTFDracoLoader.js +266 -266
  22. package/GLTFDracoLoader.ts +1 -1
  23. package/Grass/Grass.d.ts +8 -8
  24. package/Grass/Grass.js +38 -38
  25. package/Grass/index.d.ts +2 -2
  26. package/Grass/index.js +2 -2
  27. package/Ground1/Ground1.d.ts +10 -10
  28. package/Ground1/Ground1.js +71 -71
  29. package/Ground1/index.d.ts +1 -1
  30. package/Ground1/index.js +1 -1
  31. package/MeshBase.d.ts +36 -36
  32. package/MeshBase.js +247 -247
  33. package/Mirror.d.ts +25 -25
  34. package/Mirror.js +143 -143
  35. package/MktMesh/MktMesh.d.ts +301 -291
  36. package/MktMesh/MktMesh.js +1064 -1045
  37. package/MktMesh/MktMesh.ts +32 -11
  38. package/MktMesh/assetUrl.d.ts +59 -35
  39. package/MktMesh/assetUrl.js +154 -69
  40. package/MktMesh/assetUrl.ts +155 -69
  41. package/MktMesh/mktMappingShader.d.ts +12 -12
  42. package/MktMesh/mktMappingShader.js +138 -138
  43. package/MktMesh/mktMappingShader.ts +139 -139
  44. package/MktMesh/mktShader.d.ts +263 -263
  45. package/MktMesh/mktShader.js +1236 -1236
  46. package/MktMesh/mktShader.ts +1344 -1344
  47. package/MktMesh/panoBitmapTexture.d.ts +25 -25
  48. package/MktMesh/panoBitmapTexture.js +52 -52
  49. package/MktMesh/panoBitmapTexture.ts +54 -54
  50. package/MktMesh/panoSlotBind.d.ts +29 -29
  51. package/MktMesh/panoSlotBind.js +106 -106
  52. package/MktMesh/panoSlotBind.ts +153 -153
  53. package/MktMesh/panoSlotRoster.d.ts +22 -22
  54. package/MktMesh/panoSlotRoster.js +169 -169
  55. package/MktMesh/panoSlotRoster.ts +168 -168
  56. package/MktMesh/panoTileStitcher.d.ts +119 -119
  57. package/MktMesh/panoTileStitcher.js +529 -529
  58. package/MktMesh/panoTileStitcher.ts +616 -616
  59. package/MktMesh/types.d.ts +75 -75
  60. package/MktMesh/types.js +1 -1
  61. package/MktMesh/wallCapTessellate.d.ts +33 -33
  62. package/MktMesh/wallCapTessellate.js +97 -97
  63. package/MktMesh/wallCapTessellate.ts +68 -68
  64. package/PipeMesh/PathGeometry.d.ts +44 -44
  65. package/PipeMesh/PathGeometry.js +307 -307
  66. package/PipeMesh/PathPoint.d.ts +17 -17
  67. package/PipeMesh/PathPoint.js +31 -31
  68. package/PipeMesh/PathPointList.d.ts +31 -31
  69. package/PipeMesh/PathPointList.js +209 -209
  70. package/PipeMesh/PathTubeGeometry.d.ts +25 -25
  71. package/PipeMesh/PathTubeGeometry.js +130 -130
  72. package/PipeMesh/PipeMesh.d.ts +25 -25
  73. package/PipeMesh/PipeMesh.js +63 -63
  74. package/PipeMesh/index.d.ts +1 -1
  75. package/PipeMesh/index.js +1 -1
  76. package/PlaneModal1/PlaneModal1.d.ts +34 -34
  77. package/PlaneModal1/PlaneModal1.js +109 -109
  78. package/PlaneModal1/index.d.ts +1 -1
  79. package/PlaneModal1/index.js +1 -1
  80. package/PlaneText.d.ts +27 -27
  81. package/PlaneText.js +35 -35
  82. package/PlaneWithHtml.d.ts +13 -13
  83. package/PlaneWithHtml.js +64 -64
  84. package/PointLight/PointLight.d.ts +13 -13
  85. package/PointLight/PointLight.js +64 -64
  86. package/PointLight/index.d.ts +1 -1
  87. package/PointLight/index.js +1 -1
  88. package/Sky/Sky.d.ts +9 -9
  89. package/Sky/Sky.js +22 -22
  90. package/Sky/index.d.ts +1 -1
  91. package/Sky/index.js +1 -1
  92. package/SpotLight.d.ts +6 -6
  93. package/SpotLight.js +72 -72
  94. package/SpriteModal1/SpriteModal1.d.ts +33 -33
  95. package/SpriteModal1/SpriteModal1.js +116 -116
  96. package/SpriteModal1/index.d.ts +1 -1
  97. package/SpriteModal1/index.js +1 -1
  98. package/SpriteText.d.ts +46 -46
  99. package/SpriteText.js +176 -176
  100. package/SpriteText2.d.ts +48 -48
  101. package/SpriteText2.js +223 -223
  102. package/SpriteText3.d.ts +86 -86
  103. package/SpriteText3.js +517 -517
  104. package/SpriteText3.ts +599 -599
  105. package/SpriteWithHtml.d.ts +9 -9
  106. package/SpriteWithHtml.js +44 -44
  107. package/Text3D/Text3D.d.ts +20 -20
  108. package/Text3D/Text3D.js +58 -58
  109. package/Text3D/fontController.d.ts +60 -60
  110. package/Text3D/fontController.js +166 -166
  111. package/Text3D/index.d.ts +1 -1
  112. package/Text3D/index.js +1 -1
  113. package/ThreeBase.d.ts +248 -248
  114. package/ThreeBase.js +1202 -1202
  115. package/ThreeBase.ts +1314 -1314
  116. package/ThreeMouse.d.ts +53 -54
  117. package/ThreeMouse.js +453 -453
  118. package/Transition.d.ts +45 -45
  119. package/Transition.js +209 -209
  120. package/Water/Water.d.ts +5 -5
  121. package/Water/Water.js +44 -44
  122. package/Water/index.d.ts +2 -2
  123. package/Water/index.js +2 -2
  124. package/WaterFlow/FloatingDuck.d.ts +88 -88
  125. package/WaterFlow/FloatingDuck.js +307 -307
  126. package/WaterFlow/FloatingDuck.ts +445 -445
  127. package/WaterFlow/GPUFluidSimulation.d.ts +56 -56
  128. package/WaterFlow/GPUFluidSimulation.js +781 -781
  129. package/WaterFlow/GPUFluidSimulation.ts +827 -827
  130. package/WaterFlow/ReservoirSystem.d.ts +106 -106
  131. package/WaterFlow/ReservoirSystem.js +611 -611
  132. package/WaterFlow/ReservoirSystem.ts +754 -754
  133. package/WaterFlow/SPHField.d.ts +35 -35
  134. package/WaterFlow/SPHField.js +203 -203
  135. package/WaterFlow/SPHField.ts +228 -228
  136. package/WaterFlow/ScreenSpaceFluidPass.d.ts +69 -69
  137. package/WaterFlow/ScreenSpaceFluidPass.js +728 -728
  138. package/WaterFlow/ScreenSpaceFluidPass.ts +789 -789
  139. package/WaterFlow/ShallowWaterSurface.d.ts +45 -45
  140. package/WaterFlow/ShallowWaterSurface.js +438 -438
  141. package/WaterFlow/ShallowWaterSurface.ts +510 -510
  142. package/WaterFlow/WaterFlow.d.ts +87 -87
  143. package/WaterFlow/WaterFlow.js +171 -171
  144. package/WaterFlow/WaterFlow.ts +219 -219
  145. package/WaterFlow/types.d.ts +161 -161
  146. package/WaterFlow/types.js +1 -1
  147. package/WaterFlow/types.ts +189 -189
  148. package/WaterFlow/waterFlowPass.d.ts +3 -3
  149. package/WaterFlow/waterFlowPass.js +20 -20
  150. package/WaterFlow/waterFlowPass.ts +40 -40
  151. package/collisionOBB.d.ts +42 -42
  152. package/collisionOBB.js +112 -112
  153. package/collisionOBB.ts +108 -108
  154. package/declare.d.ts +25 -25
  155. package/index.d.ts +1 -1
  156. package/index.js +1 -1
  157. package/instanced/InstancedBatch.d.ts +57 -57
  158. package/instanced/InstancedBatch.js +348 -348
  159. package/instanced/InstancedBatch.ts +406 -406
  160. package/instanced/InstancedChild.d.ts +174 -174
  161. package/instanced/InstancedChild.js +264 -264
  162. package/instanced/InstancedChild.ts +327 -327
  163. package/instanced/InstancedGroup.d.ts +43 -43
  164. package/instanced/InstancedGroup.js +126 -126
  165. package/instanced/InstancedGroup.ts +137 -137
  166. package/instanced/InstancedMeshBase.d.ts +38 -38
  167. package/instanced/InstancedMeshBase.js +282 -282
  168. package/instanced/InstancedTemplate.d.ts +46 -46
  169. package/instanced/InstancedTemplate.js +125 -125
  170. package/keyControls.d.ts +29 -30
  171. package/keyControls.js +101 -101
  172. package/lensflare/LensFlare.d.ts +39 -39
  173. package/lensflare/LensFlare.js +284 -284
  174. package/package.json +6 -1
  175. package/pass/bloom_pass.d.ts +2 -2
  176. package/pass/bloom_pass.js +174 -174
  177. package/pass/cover_pass.d.ts +2 -2
  178. package/pass/cover_pass.js +108 -108
  179. package/pass/debugDepthState.d.ts +20 -20
  180. package/pass/debugDepthState.js +9 -9
  181. package/pass/debugDepthState.ts +22 -22
  182. package/pass/depthTestBias.d.ts +12 -12
  183. package/pass/depthTestBias.js +12 -12
  184. package/pass/depthTestBias.ts +12 -12
  185. package/pass/effectUserData.d.ts +27 -27
  186. package/pass/effectUserData.js +1 -1
  187. package/pass/effectUserData.ts +46 -46
  188. package/pass/frosted_glass_pass.d.ts +2 -2
  189. package/pass/frosted_glass_pass.js +150 -150
  190. package/pass/fsQuad.d.ts +9 -9
  191. package/pass/fsQuad.js +28 -28
  192. package/pass/glow_pass.d.ts +2 -2
  193. package/pass/glow_pass.js +350 -350
  194. package/pass/screen_bloom_pass.d.ts +11 -11
  195. package/pass/screen_bloom_pass.js +136 -136
  196. package/pass/ssao_pass.d.ts +88 -88
  197. package/pass/ssao_pass.js +799 -799
  198. package/pass/ssao_pass.ts +918 -918
  199. package/pass/stroke_pass.d.ts +2 -2
  200. package/pass/stroke_pass.js +267 -267
  201. package/shaders/FXAAShaderMaterial.d.ts +3 -3
  202. package/shaders/FXAAShaderMaterial.js +20 -20
  203. package/shaders/baseDepthVisShader.d.ts +11 -11
  204. package/shaders/baseDepthVisShader.js +36 -36
  205. package/shaders/baseDepthVisShader.ts +36 -36
  206. package/shaders/baseTextureToRenderShader.d.ts +2 -2
  207. package/shaders/baseTextureToRenderShader.js +19 -19
  208. package/shaders/copyShader.d.ts +3 -3
  209. package/shaders/copyShader.js +13 -13
  210. package/shaders/debugDepthCompareShader.d.ts +14 -14
  211. package/shaders/debugDepthCompareShader.js +49 -49
  212. package/shaders/debugDepthCompareShader.ts +50 -50
  213. package/shaders/debugDepthJudgeShader.d.ts +18 -18
  214. package/shaders/debugDepthJudgeShader.js +52 -52
  215. package/shaders/debugDepthJudgeShader.ts +54 -54
  216. package/shaders/debugExcludedShader.d.ts +13 -13
  217. package/shaders/debugExcludedShader.js +46 -46
  218. package/shaders/debugExcludedShader.ts +48 -48
  219. package/spriteTextBg.d.ts +1 -1
  220. package/spriteTextBg.js +20 -20
  221. package/spriteTextBg.ts +20 -20
  222. package/threeLoader.d.ts +35 -35
  223. package/threeLoader.js +518 -518
  224. package/threeUtils.d.ts +53 -53
  225. package/threeUtils.js +329 -329
  226. package/types.d.ts +2 -2
  227. package/types.js +6 -6
@@ -1,169 +1,169 @@
1
- /*
2
- * ⭐ 槽位名册纯函数:**「中心 + 序号邻居」**定 shader 那 N 格装哪 N 张全景(皇上旨 2026-10-02 晚;
3
- * 2026-10-06 晚旨「一次展示 8 个全景」⇒ N 从 4 变 8,靠「每个全景只占左右 2 张 RT」腾出 sampler)。
4
- *
5
- * 旨意原文(verbatim):「我想要把按距离筛选的逻辑, 改一改, 首先, 按照 全景到相机的距离选中第一个,
6
- * 然后按照这个全景的序号, 前后各添加一个全景, 举个例子, 通过计算 5号 全景距离相机最近,
7
- * 那就选出一个 5号全景填入 shader 然后再, 5号前后是 4号 和 6号, 也分别填入 shader,
8
- * 最后再判断一下, 如果相机距离4号的距离 比 相机距离6号的距离近 就再追加一个[它外侧那张]全景, 反之就追加一个 7号 全景,
9
- * 如果没有 目标全景, 比如 1号全景往前 没有 -1 -2 号全景, shader 里面就留空」
10
- * ⭐ 同日追问三择(verbatim):「补 3 号(顺着往外扩一张)」/「中心没换人就维持整组」/
11
- * 探针第一行「打成『中心#5 + 邻居 4/6/7』」。
12
- * ⭐ 皇上旨 2026-10-07(第二十道,verbatim):「shader 是可以支持最多传入8个全景的, 所以尽可能得填满8个全景位置」
13
- * ⇒ 收窄上面那句「如果没有目标全景…就留空」的适用边界:**留空只发生在「项目里的全景总数不够一格一人」时**;
14
- * 序号越界的那个位置根本不是一张全景 ⇒ 跳过它、继续往还有货的那一侧扩,槽位不许白留给「不存在的序号」。
15
- * 同一道旨还要求:新加的全景点**不必等中心换人**才进 shader ⇒ 中心没换人时在册的人照旧一格不动,空格当场补满。
16
- * ⚠️ 上限仍是 `MKT_PANO_MAX_SLOTS`(=8):8 点 × 左右 2 张拼合槽 = 16 个 sampler,那是 GLSL 物理闸
17
- * (皇上机器 maxTextures=16)⇒ 本函数不越那道闸,只是把那 8 格**尽量用满**。
18
- * ⭐ 皇上旨 2026-10-07 第二十一道旨(verbatim):「判断使用那些全景球的判断条件, 从距离相机的距离 改成
19
- * 判断距离控制器的中心点的距离来判断」⇒ **本函数的尺子另一端换了人**:函数体一个字不改(它只吃调用方算好的
20
- * `d`),改的是**调用方**——编辑态与预览的锚点 = 轨道控制器注视点 `controls.target`(画面正中央那个点),
21
- * 发布页那一路没有控制器 ⇒ 回落相机位置。下面所有「相机」二字请按「锚点(= 控制器中心点,未注入时才是相机)」读;
22
- * 10-02 那道旨的原文里「距离相机最近」是**历史引文**,逐字保留。
23
- * ⚠️ 同一把尺还喂着 `camW`(混合权重)⇒ 权重跟着换锚点;而面上「取哪一张」的 `score = 顶点距离 − 夹角`
24
- * 里**根本没有相机量**(09-28 15:07 七修亲自撤掉 camD 项),不受本道旨影响。
25
- *
26
- * 一句话口径:
27
- * 1) **中心** = 到**锚点**(调用方给的水平距离 XZ;锚点 = 控制器中心点,见上方 10-07 那道旨)最近那张;
28
- * ⚠️ 带死区 `margin`:别人必须比在册中心**近出 margin 米以上**
29
- * 才抢走中心 ⇒ 锚点在等距带抖动时整组一动不动(09-26 那条「其他 3 个依然不动」的稳定诉求搬到这里来用)。
30
- * 2) 中心定了之后按**列表序号**(= 面板列表顺序 = 日志里那个 `#i`)取邻居:`中心-1`、`中心+1` 各一张。
31
- * 3) 再往外一层层扩(`中心±2`、`中心±3`…)直到凑够槽数;**同一层里先取离锚点更近那一侧**
32
- * (平手归序号小的那侧)。⭐ 2026-10-06 晚旨「一次展示 8 个」⇒ 槽数 4 → 8,这里从「只扩一层」
33
- * 改成一层层扩下去;前 4 张的顺序与 4 槽时代**逐字相同**(中心、-1、+1、更近那侧的 ±2)。
34
- * 4) ⭐ 2026-10-07 皇上旨「shader 是可以支持最多传入 8 个全景的, 所以尽可能得填满 8 个全景位置」
35
- * ⇒ **改写 10-02 那句「没有目标全景就留空」的适用边界**:越界的那个**序号**直接跳过(它本来就不是一个全景),
36
- * 外扩**继续往还有货的那一侧**走 ⇒ 只要列表里还有没用过的全景,槽就一直被填,直到凑够 `maxSlots`。
37
- * ⛔ 只有「整个列表都被请进来了还不够一格一人的时候」(= 项目里的全景总数 < 槽数)才留空 ——
38
- * 那是物理不够,不是策略留白。旧行为(中心贴列表两端 ⇒ 明明还有 5 张没用上却空着 3 格)作废。
39
- * 5) ⭐ 中心没换人 ⇒ **在册的人一格都不动**(10-02 当日亲择,照旧);但 10-07 那道旨补了后半句:
40
- * **空格要当场补上** ⇒ 新增的全景点不必等「中心换人」才进 shader(否则他一张一张加点时永远填不满)。
41
- *
42
- * ⚠️ 与历代口径的关系(别搞混):
43
- * - 09-25「槽位与相机完全无关」→ 09-26「名册增量换人(一进一出)」→ 09-27「在册者按相机距离落槽、取最近 4 个」
44
- * ⇒ 本函数把 09-27 那半条**作废**:不再取「最近 4 个」,改取「最近那一张的序号邻居」,槽号也不再按距离排。
45
- * - 09-26 的「一进一出 + 0.5m 死区」精神保留,但对象从「谁挤掉谁」变成「谁能抢走中心」。
46
- *
47
- * ⚠️ 为什么 0 号槽必须是中心:立方体(`FurnitureObject`)那份 `BoxGeometry` **没有** `aPanoIndex` attribute ⇒
48
- * 序号映射 shader 里 `vPanoIndex` 恒 0 ⇒ 立方体显示的就是名册第 0 格那一张(皇上旨 10-02「模型也按距离相机最近的方式
49
- * 设置全景参数」的落点)。中心坐别的格 = 立方体显示错图。
50
- *
51
- * ⚠️ 为什么单独成文件:本函数零依赖(不碰 three / MobX / DOM),`test/mktmesh.test.js` 的 **AP 组**会用 esbuild
52
- * 把**这份源码原文**转译后真跑一遍(中心/邻居/外扩/越界不占格/死区/删点/幂等/空格回填 各断言一次)。
53
- * ⇒ 改这里的算法,那条数字测试立刻知道;⛔ 别把逻辑搬回渲染器里,那样就只能靠正则钉、证不了行为。
54
- *
55
- * ⭐ 皇上旨 2026-10-03「库侧也一并改成中心 ± 邻居」⇒ 本文件从 `src/views/MktMeshEdit/` **搬进库里**
56
- * (`three-base/MktMesh/`):编辑态(`mktMeshEditRenderer`)与预览/发布态(`MktMesh.updateTexture` +
57
- * `feedFaceMapping`)**共用这一份算法和下面那一个死区常数**,⛔ 不许在任一侧再抄一份 0.5 或另写一套挑图。
58
- */
59
- /** ⭐ 槽位「中心死区」(米):离**锚点**(控制器中心点;发布页未注入时 = 相机位置)水平距离最近的那张是中心;挑战者必须比现任中心**近出这么多**才抢得走。
60
- * 没有死区 ⇒ 锚点停在两点的等距带附近每帧换中心 ⇒ 换中心 = 整组邻居重排 = 一整组瓦片重绑(正是 09-24/25 报的「切全景卡一下」)。
61
- * 定义在此是因为编辑态与库侧共用(全项目**只此一处**,两侧都 import 它)。 */
62
- export const PANO_SLOT_SWAP_MARGIN_M = 0.5;
63
- /**
64
- * 算出下一帧的槽位名册(**不修改传进来的 roster**,返回新数组)。
65
- * @param roster 当前名册(0 号槽 = 上一帧的中心),长度可以小于 maxSlots(内部按 undefined 补齐)
66
- * @param dists 本帧全部全景点及其到**锚点**的距离(锚点 = 调用方那把尺子的端点;⭐ 10-07 第二十一道旨后 = 控制器中心点),**数组顺序 = 全景列表顺序**(下标就是旨意里说的「几号全景」)
67
- * @param maxSlots shader 的槽位上限(= `MKT_PANO_MAX_SLOTS`;⭐ 2026-10-06 晚旨后是 **8**:8 点 × 每个全景
68
- * 左右 2 张 RT = 16 sampler 仍是 GLSL 物理上限。⛔ 本函数不许假设它恒等于 4)
69
- * @param margin 抢中心的死区(米,= `PANO_SLOT_SWAP_MARGIN_M`)
70
- * @returns 长度恒 = maxSlots 的新名册:**0 号槽 = 中心**,其余槽 = 列表里按序号一层层往外扩的那些
71
- * (同一层先取离锚点更近那侧)。⭐ 10-07 旨「尽可能填满」⇒ 越界的序号不占格、外扩继续往有货那侧走,
72
- * 所以**填几格 = min(项目全景总数, maxSlots)**;只有列表里的人不够时才留空(= `undefined`)。
73
- * 中心没换人 ⇒ 在册的一格都不动,只把**空格**补上。
74
- */
75
- export function panoSlotRosterStep(roster, dists, maxSlots, margin) {
76
- const next = roster.slice(0, maxSlots);
77
- while (next.length < maxSlots)
78
- next.push(undefined);
79
- const alive = new Set(dists.map((n) => n.t));
80
- // ① 已被删掉的点先腾槽(名册里躺着一个不存在的点 = 那格的矩阵与权重都是旧账)
81
- for (let s = 0; s < maxSlots; s++)
82
- if (next[s] && !alive.has(next[s]))
83
- next[s] = undefined;
84
- if (!dists.length)
85
- return next.fill(undefined);
86
- // ② 在册中心 = 0 号槽那位;别人必须比它近出 margin 以上才换中心
87
- const incumbent = next[0] !== undefined && alive.has(next[0]) ? next[0] : undefined;
88
- let nearest = 0;
89
- for (let i = 1; i < dists.length; i++)
90
- if (dists[i].d < dists[nearest].d)
91
- nearest = i;
92
- const incIdx = incumbent === undefined ? -1 : dists.findIndex((n) => n.t === incumbent);
93
- const centerIdx = incIdx < 0 || dists[nearest].d < dists[incIdx].d - margin ? nearest : incIdx;
94
- // ③ 目标清单 = 中心、列表前一张、后一张,然后**按「离锚点更近那一侧优先」一层层往外扩**,
95
- // 直到凑够 maxSlots。⭐ 2026-10-06 晚皇上旨「一次能够展示 8 个全景纹理」⇒ maxSlots 由 4 变 8,
96
- // 此处从「只扩一层」改成「一层层扩下去」。扩的**顺序**沿用当日那句「更近那侧再往外一张」:
97
- // k=2 那一轮先取更近那侧 ⇒ 前 4 张与 4 槽时代**逐字相同**(中心、-1、+1、更近那侧的 ±2),
98
- // 多出来的 4 张继续 ±3、±4…
99
- // ⭐ 2026-10-07 旨「尽可能得填满 8 个全景位置」⇒ 越界的那个**序号**直接跳过、**不占一格**,
100
- // 外扩继续往还有货的那一侧走(旧写法把 `undefined` 也塞进清单去占槽 ⇒ 10 个点、中心贴列表首端时
101
- // 只填 5 格,剩下 5 张全景明明存在却进不了 shader)。清单里只装真实存在的全景
102
- // ⇒ 填几格 = **min(项目全景总数, maxSlots)**,只有人不够时才留空(⛔ 不复制一张来凑数)。
103
- const at = (i) => (i >= 0 && i < dists.length ? dists[i].t : undefined);
104
- const lo = centerIdx - 1;
105
- const hi = centerIdx + 1;
106
- const dLo = lo >= 0 && lo < dists.length ? dists[lo].d : Infinity;
107
- const dHi = hi >= 0 && hi < dists.length ? dists[hi].d : Infinity;
108
- const nearSign = dLo <= dHi ? -1 : 1; // 更近那侧:-1 = 往前(序号更小),+1 = 往后;平手归序号小的那侧
109
- const targets = [];
110
- const push = (i) => {
111
- if (targets.length >= maxSlots)
112
- return;
113
- const t = at(i);
114
- if (t !== undefined)
115
- targets.push(t);
116
- };
117
- push(centerIdx);
118
- push(lo);
119
- push(hi);
120
- // k 超过列表长度 ⇒ 两侧都再也请不到人,循环自然停(⛔ 别写成「直到填满」的无界循环)
121
- for (let k = 2; targets.length < maxSlots && k <= dists.length; k++) {
122
- push(centerIdx + nearSign * k);
123
- push(centerIdx - nearSign * k);
124
- }
125
- const used = new Set();
126
- used.add(targets[0]);
127
- // ④ ⭐ 中心没换人(10-02 当日亲择「维持整组」)⇒ 在册的人**一格都不动**,只把空格补上
128
- // (10-07 那道旨的后半句):他一张一张加全景时,新增那张立刻进得了 shader,不用等中心换人;
129
- // 删掉一张留下的那格也当场补。已有格子一字节都不重绑 ⇒ 没有任何换人/重传代价。
130
- if (incIdx >= 0 && centerIdx === incIdx) {
131
- const kept = next.slice();
132
- kept[0] = targets[0];
133
- for (const x of kept)
134
- if (x !== undefined)
135
- used.add(x);
136
- for (const t of targets) {
137
- if (used.has(t))
138
- continue;
139
- const hole = kept.indexOf(undefined);
140
- if (hole < 1)
141
- break; // -1 = 没有空格;0 = 0 号槽恒归中心(这里不可能发生,兜住)
142
- kept[hole] = t;
143
- used.add(t);
144
- }
145
- return kept;
146
- }
147
- // ⑤ 中心换人 ⇒ 整组按**新中心**的序号清单重算,但「仍在清单里的人留在原格」
148
- // ⇒ 中心挪一格时只有必要的格重绑瓦片。0 号槽恒 = 中心(立方体 `vPanoIndex` 恒 0,它显示的就是这一格)。
149
- const placed = new Array(maxSlots).fill(undefined);
150
- placed[0] = targets[0];
151
- const keepable = (x) => x !== undefined && targets.indexOf(x) >= 0 && !used.has(x);
152
- for (let s = 1; s < maxSlots; s++) {
153
- if (keepable(next[s])) {
154
- placed[s] = next[s];
155
- used.add(next[s]);
156
- }
157
- }
158
- for (let s = 1; s < maxSlots; s++) {
159
- if (placed[s] !== undefined)
160
- continue;
161
- const fresh = targets.find((x) => !used.has(x));
162
- // 清单里的人全请完了还空 ⇒ 项目里的全景本来就不够一格一人(总数 < maxSlots),这一格留空
163
- if (fresh === undefined)
164
- continue;
165
- placed[s] = fresh;
166
- used.add(fresh);
167
- }
168
- return placed;
169
- }
1
+ /*
2
+ * ⭐ 槽位名册纯函数:**「中心 + 序号邻居」**定 shader 那 N 格装哪 N 张全景(皇上旨 2026-10-02 晚;
3
+ * 2026-10-06 晚旨「一次展示 8 个全景」⇒ N 从 4 变 8,靠「每个全景只占左右 2 张 RT」腾出 sampler)。
4
+ *
5
+ * 旨意原文(verbatim):「我想要把按距离筛选的逻辑, 改一改, 首先, 按照 全景到相机的距离选中第一个,
6
+ * 然后按照这个全景的序号, 前后各添加一个全景, 举个例子, 通过计算 5号 全景距离相机最近,
7
+ * 那就选出一个 5号全景填入 shader 然后再, 5号前后是 4号 和 6号, 也分别填入 shader,
8
+ * 最后再判断一下, 如果相机距离4号的距离 比 相机距离6号的距离近 就再追加一个[它外侧那张]全景, 反之就追加一个 7号 全景,
9
+ * 如果没有 目标全景, 比如 1号全景往前 没有 -1 -2 号全景, shader 里面就留空」
10
+ * ⭐ 同日追问三择(verbatim):「补 3 号(顺着往外扩一张)」/「中心没换人就维持整组」/
11
+ * 探针第一行「打成『中心#5 + 邻居 4/6/7』」。
12
+ * ⭐ 皇上旨 2026-10-07(第二十道,verbatim):「shader 是可以支持最多传入8个全景的, 所以尽可能得填满8个全景位置」
13
+ * ⇒ 收窄上面那句「如果没有目标全景…就留空」的适用边界:**留空只发生在「项目里的全景总数不够一格一人」时**;
14
+ * 序号越界的那个位置根本不是一张全景 ⇒ 跳过它、继续往还有货的那一侧扩,槽位不许白留给「不存在的序号」。
15
+ * 同一道旨还要求:新加的全景点**不必等中心换人**才进 shader ⇒ 中心没换人时在册的人照旧一格不动,空格当场补满。
16
+ * ⚠️ 上限仍是 `MKT_PANO_MAX_SLOTS`(=8):8 点 × 左右 2 张拼合槽 = 16 个 sampler,那是 GLSL 物理闸
17
+ * (皇上机器 maxTextures=16)⇒ 本函数不越那道闸,只是把那 8 格**尽量用满**。
18
+ * ⭐ 皇上旨 2026-10-07 第二十一道旨(verbatim):「判断使用那些全景球的判断条件, 从距离相机的距离 改成
19
+ * 判断距离控制器的中心点的距离来判断」⇒ **本函数的尺子另一端换了人**:函数体一个字不改(它只吃调用方算好的
20
+ * `d`),改的是**调用方**——编辑态与预览的锚点 = 轨道控制器注视点 `controls.target`(画面正中央那个点),
21
+ * 发布页那一路没有控制器 ⇒ 回落相机位置。下面所有「相机」二字请按「锚点(= 控制器中心点,未注入时才是相机)」读;
22
+ * 10-02 那道旨的原文里「距离相机最近」是**历史引文**,逐字保留。
23
+ * ⚠️ 同一把尺还喂着 `camW`(混合权重)⇒ 权重跟着换锚点;而面上「取哪一张」的 `score = 顶点距离 − 夹角`
24
+ * 里**根本没有相机量**(09-28 15:07 七修亲自撤掉 camD 项),不受本道旨影响。
25
+ *
26
+ * 一句话口径:
27
+ * 1) **中心** = 到**锚点**(调用方给的水平距离 XZ;锚点 = 控制器中心点,见上方 10-07 那道旨)最近那张;
28
+ * ⚠️ 带死区 `margin`:别人必须比在册中心**近出 margin 米以上**
29
+ * 才抢走中心 ⇒ 锚点在等距带抖动时整组一动不动(09-26 那条「其他 3 个依然不动」的稳定诉求搬到这里来用)。
30
+ * 2) 中心定了之后按**列表序号**(= 面板列表顺序 = 日志里那个 `#i`)取邻居:`中心-1`、`中心+1` 各一张。
31
+ * 3) 再往外一层层扩(`中心±2`、`中心±3`…)直到凑够槽数;**同一层里先取离锚点更近那一侧**
32
+ * (平手归序号小的那侧)。⭐ 2026-10-06 晚旨「一次展示 8 个」⇒ 槽数 4 → 8,这里从「只扩一层」
33
+ * 改成一层层扩下去;前 4 张的顺序与 4 槽时代**逐字相同**(中心、-1、+1、更近那侧的 ±2)。
34
+ * 4) ⭐ 2026-10-07 皇上旨「shader 是可以支持最多传入 8 个全景的, 所以尽可能得填满 8 个全景位置」
35
+ * ⇒ **改写 10-02 那句「没有目标全景就留空」的适用边界**:越界的那个**序号**直接跳过(它本来就不是一个全景),
36
+ * 外扩**继续往还有货的那一侧**走 ⇒ 只要列表里还有没用过的全景,槽就一直被填,直到凑够 `maxSlots`。
37
+ * ⛔ 只有「整个列表都被请进来了还不够一格一人的时候」(= 项目里的全景总数 < 槽数)才留空 ——
38
+ * 那是物理不够,不是策略留白。旧行为(中心贴列表两端 ⇒ 明明还有 5 张没用上却空着 3 格)作废。
39
+ * 5) ⭐ 中心没换人 ⇒ **在册的人一格都不动**(10-02 当日亲择,照旧);但 10-07 那道旨补了后半句:
40
+ * **空格要当场补上** ⇒ 新增的全景点不必等「中心换人」才进 shader(否则他一张一张加点时永远填不满)。
41
+ *
42
+ * ⚠️ 与历代口径的关系(别搞混):
43
+ * - 09-25「槽位与相机完全无关」→ 09-26「名册增量换人(一进一出)」→ 09-27「在册者按相机距离落槽、取最近 4 个」
44
+ * ⇒ 本函数把 09-27 那半条**作废**:不再取「最近 4 个」,改取「最近那一张的序号邻居」,槽号也不再按距离排。
45
+ * - 09-26 的「一进一出 + 0.5m 死区」精神保留,但对象从「谁挤掉谁」变成「谁能抢走中心」。
46
+ *
47
+ * ⚠️ 为什么 0 号槽必须是中心:立方体(`FurnitureObject`)那份 `BoxGeometry` **没有** `aPanoIndex` attribute ⇒
48
+ * 序号映射 shader 里 `vPanoIndex` 恒 0 ⇒ 立方体显示的就是名册第 0 格那一张(皇上旨 10-02「模型也按距离相机最近的方式
49
+ * 设置全景参数」的落点)。中心坐别的格 = 立方体显示错图。
50
+ *
51
+ * ⚠️ 为什么单独成文件:本函数零依赖(不碰 three / MobX / DOM),`test/mktmesh.test.js` 的 **AP 组**会用 esbuild
52
+ * 把**这份源码原文**转译后真跑一遍(中心/邻居/外扩/越界不占格/死区/删点/幂等/空格回填 各断言一次)。
53
+ * ⇒ 改这里的算法,那条数字测试立刻知道;⛔ 别把逻辑搬回渲染器里,那样就只能靠正则钉、证不了行为。
54
+ *
55
+ * ⭐ 皇上旨 2026-10-03「库侧也一并改成中心 ± 邻居」⇒ 本文件从 `src/views/MktMeshEdit/` **搬进库里**
56
+ * (`three-base/MktMesh/`):编辑态(`mktMeshEditRenderer`)与预览/发布态(`MktMesh.updateTexture` +
57
+ * `feedFaceMapping`)**共用这一份算法和下面那一个死区常数**,⛔ 不许在任一侧再抄一份 0.5 或另写一套挑图。
58
+ */
59
+ /** ⭐ 槽位「中心死区」(米):离**锚点**(控制器中心点;发布页未注入时 = 相机位置)水平距离最近的那张是中心;挑战者必须比现任中心**近出这么多**才抢得走。
60
+ * 没有死区 ⇒ 锚点停在两点的等距带附近每帧换中心 ⇒ 换中心 = 整组邻居重排 = 一整组瓦片重绑(正是 09-24/25 报的「切全景卡一下」)。
61
+ * 定义在此是因为编辑态与库侧共用(全项目**只此一处**,两侧都 import 它)。 */
62
+ export const PANO_SLOT_SWAP_MARGIN_M = 0.5;
63
+ /**
64
+ * 算出下一帧的槽位名册(**不修改传进来的 roster**,返回新数组)。
65
+ * @param roster 当前名册(0 号槽 = 上一帧的中心),长度可以小于 maxSlots(内部按 undefined 补齐)
66
+ * @param dists 本帧全部全景点及其到**锚点**的距离(锚点 = 调用方那把尺子的端点;⭐ 10-07 第二十一道旨后 = 控制器中心点),**数组顺序 = 全景列表顺序**(下标就是旨意里说的「几号全景」)
67
+ * @param maxSlots shader 的槽位上限(= `MKT_PANO_MAX_SLOTS`;⭐ 2026-10-06 晚旨后是 **8**:8 点 × 每个全景
68
+ * 左右 2 张 RT = 16 sampler 仍是 GLSL 物理上限。⛔ 本函数不许假设它恒等于 4)
69
+ * @param margin 抢中心的死区(米,= `PANO_SLOT_SWAP_MARGIN_M`)
70
+ * @returns 长度恒 = maxSlots 的新名册:**0 号槽 = 中心**,其余槽 = 列表里按序号一层层往外扩的那些
71
+ * (同一层先取离锚点更近那侧)。⭐ 10-07 旨「尽可能填满」⇒ 越界的序号不占格、外扩继续往有货那侧走,
72
+ * 所以**填几格 = min(项目全景总数, maxSlots)**;只有列表里的人不够时才留空(= `undefined`)。
73
+ * 中心没换人 ⇒ 在册的一格都不动,只把**空格**补上。
74
+ */
75
+ export function panoSlotRosterStep(roster, dists, maxSlots, margin) {
76
+ const next = roster.slice(0, maxSlots);
77
+ while (next.length < maxSlots)
78
+ next.push(undefined);
79
+ const alive = new Set(dists.map((n) => n.t));
80
+ // ① 已被删掉的点先腾槽(名册里躺着一个不存在的点 = 那格的矩阵与权重都是旧账)
81
+ for (let s = 0; s < maxSlots; s++)
82
+ if (next[s] && !alive.has(next[s]))
83
+ next[s] = undefined;
84
+ if (!dists.length)
85
+ return next.fill(undefined);
86
+ // ② 在册中心 = 0 号槽那位;别人必须比它近出 margin 以上才换中心
87
+ const incumbent = next[0] !== undefined && alive.has(next[0]) ? next[0] : undefined;
88
+ let nearest = 0;
89
+ for (let i = 1; i < dists.length; i++)
90
+ if (dists[i].d < dists[nearest].d)
91
+ nearest = i;
92
+ const incIdx = incumbent === undefined ? -1 : dists.findIndex((n) => n.t === incumbent);
93
+ const centerIdx = incIdx < 0 || dists[nearest].d < dists[incIdx].d - margin ? nearest : incIdx;
94
+ // ③ 目标清单 = 中心、列表前一张、后一张,然后**按「离锚点更近那一侧优先」一层层往外扩**,
95
+ // 直到凑够 maxSlots。⭐ 2026-10-06 晚皇上旨「一次能够展示 8 个全景纹理」⇒ maxSlots 由 4 变 8,
96
+ // 此处从「只扩一层」改成「一层层扩下去」。扩的**顺序**沿用当日那句「更近那侧再往外一张」:
97
+ // k=2 那一轮先取更近那侧 ⇒ 前 4 张与 4 槽时代**逐字相同**(中心、-1、+1、更近那侧的 ±2),
98
+ // 多出来的 4 张继续 ±3、±4…
99
+ // ⭐ 2026-10-07 旨「尽可能得填满 8 个全景位置」⇒ 越界的那个**序号**直接跳过、**不占一格**,
100
+ // 外扩继续往还有货的那一侧走(旧写法把 `undefined` 也塞进清单去占槽 ⇒ 10 个点、中心贴列表首端时
101
+ // 只填 5 格,剩下 5 张全景明明存在却进不了 shader)。清单里只装真实存在的全景
102
+ // ⇒ 填几格 = **min(项目全景总数, maxSlots)**,只有人不够时才留空(⛔ 不复制一张来凑数)。
103
+ const at = (i) => (i >= 0 && i < dists.length ? dists[i].t : undefined);
104
+ const lo = centerIdx - 1;
105
+ const hi = centerIdx + 1;
106
+ const dLo = lo >= 0 && lo < dists.length ? dists[lo].d : Infinity;
107
+ const dHi = hi >= 0 && hi < dists.length ? dists[hi].d : Infinity;
108
+ const nearSign = dLo <= dHi ? -1 : 1; // 更近那侧:-1 = 往前(序号更小),+1 = 往后;平手归序号小的那侧
109
+ const targets = [];
110
+ const push = (i) => {
111
+ if (targets.length >= maxSlots)
112
+ return;
113
+ const t = at(i);
114
+ if (t !== undefined)
115
+ targets.push(t);
116
+ };
117
+ push(centerIdx);
118
+ push(lo);
119
+ push(hi);
120
+ // k 超过列表长度 ⇒ 两侧都再也请不到人,循环自然停(⛔ 别写成「直到填满」的无界循环)
121
+ for (let k = 2; targets.length < maxSlots && k <= dists.length; k++) {
122
+ push(centerIdx + nearSign * k);
123
+ push(centerIdx - nearSign * k);
124
+ }
125
+ const used = new Set();
126
+ used.add(targets[0]);
127
+ // ④ ⭐ 中心没换人(10-02 当日亲择「维持整组」)⇒ 在册的人**一格都不动**,只把空格补上
128
+ // (10-07 那道旨的后半句):他一张一张加全景时,新增那张立刻进得了 shader,不用等中心换人;
129
+ // 删掉一张留下的那格也当场补。已有格子一字节都不重绑 ⇒ 没有任何换人/重传代价。
130
+ if (incIdx >= 0 && centerIdx === incIdx) {
131
+ const kept = next.slice();
132
+ kept[0] = targets[0];
133
+ for (const x of kept)
134
+ if (x !== undefined)
135
+ used.add(x);
136
+ for (const t of targets) {
137
+ if (used.has(t))
138
+ continue;
139
+ const hole = kept.indexOf(undefined);
140
+ if (hole < 1)
141
+ break; // -1 = 没有空格;0 = 0 号槽恒归中心(这里不可能发生,兜住)
142
+ kept[hole] = t;
143
+ used.add(t);
144
+ }
145
+ return kept;
146
+ }
147
+ // ⑤ 中心换人 ⇒ 整组按**新中心**的序号清单重算,但「仍在清单里的人留在原格」
148
+ // ⇒ 中心挪一格时只有必要的格重绑瓦片。0 号槽恒 = 中心(立方体 `vPanoIndex` 恒 0,它显示的就是这一格)。
149
+ const placed = new Array(maxSlots).fill(undefined);
150
+ placed[0] = targets[0];
151
+ const keepable = (x) => x !== undefined && targets.indexOf(x) >= 0 && !used.has(x);
152
+ for (let s = 1; s < maxSlots; s++) {
153
+ if (keepable(next[s])) {
154
+ placed[s] = next[s];
155
+ used.add(next[s]);
156
+ }
157
+ }
158
+ for (let s = 1; s < maxSlots; s++) {
159
+ if (placed[s] !== undefined)
160
+ continue;
161
+ const fresh = targets.find((x) => !used.has(x));
162
+ // 清单里的人全请完了还空 ⇒ 项目里的全景本来就不够一格一人(总数 < maxSlots),这一格留空
163
+ if (fresh === undefined)
164
+ continue;
165
+ placed[s] = fresh;
166
+ used.add(fresh);
167
+ }
168
+ return placed;
169
+ }