@cesium/engine 23.0.1 → 25.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 (398) hide show
  1. package/Build/Workers/{chunk-ZEMJQKHD.js → chunk-35H3UBIO.js} +13 -12
  2. package/Build/Workers/{chunk-PQTSXJBJ.js → chunk-3LSD7OOA.js} +16 -16
  3. package/Build/Workers/{chunk-PUO7BYDY.js → chunk-3RFFPH4M.js} +1 -1
  4. package/Build/Workers/{chunk-PBECJOWF.js → chunk-3TKLDHV3.js} +2 -2
  5. package/Build/Workers/{chunk-TMCTZ5E3.js → chunk-3VDDRF2E.js} +14 -14
  6. package/Build/Workers/{chunk-FKU77FNM.js → chunk-3XY3MVPG.js} +4 -4
  7. package/Build/Workers/{chunk-2OBWHTIC.js → chunk-4GF4MVPY.js} +7 -7
  8. package/Build/Workers/{chunk-JUKGMJX7.js → chunk-4MTRQFJP.js} +3 -2
  9. package/Build/Workers/{chunk-66OWUDO7.js → chunk-4QQXGTCE.js} +8 -8
  10. package/Build/Workers/{chunk-ALTCIHRH.js → chunk-4XXHJI6Y.js} +17 -17
  11. package/Build/Workers/{chunk-K7UTK4OM.js → chunk-5T6QQAJW.js} +3 -2
  12. package/Build/Workers/{chunk-IJ3SUMK3.js → chunk-6SDGQI27.js} +3 -2
  13. package/Build/Workers/{chunk-FXSRA5UG.js → chunk-77RL3MBD.js} +6 -5
  14. package/Build/Workers/{chunk-G6MJ3ZW3.js → chunk-7LSFAEWF.js} +12 -11
  15. package/Build/Workers/{chunk-C6HHBKT5.js → chunk-A7A433MD.js} +5 -5
  16. package/Build/Workers/{chunk-PGZ3B6CB.js → chunk-A7ZBMVFS.js} +14 -14
  17. package/Build/Workers/{chunk-OZYB3AOR.js → chunk-ACFFCHHZ.js} +11 -11
  18. package/Build/Workers/{chunk-DNMASBMH.js → chunk-AEAVLYPS.js} +2 -2
  19. package/Build/Workers/{chunk-VPWYHFQA.js → chunk-AWFZHD2B.js} +4 -4
  20. package/Build/Workers/{chunk-TFPG3ZKW.js → chunk-BTX2NL3P.js} +59 -46
  21. package/Build/Workers/{chunk-TNXOPEIG.js → chunk-BVAIWR7O.js} +12 -12
  22. package/Build/Workers/chunk-CKQP3DSS.js +973 -0
  23. package/Build/Workers/{chunk-N6HRZLS6.js → chunk-CZ23Y3RM.js} +2 -2
  24. package/Build/Workers/{chunk-EIC3VAOZ.js → chunk-DFEI5MAV.js} +7 -7
  25. package/Build/Workers/{chunk-BTP3634E.js → chunk-DH26SNAB.js} +4 -1
  26. package/Build/Workers/{chunk-TXYQNXNW.js → chunk-DYT5NR6P.js} +3 -3
  27. package/Build/Workers/{chunk-O67UP5YO.js → chunk-EZARA5FJ.js} +13 -13
  28. package/Build/Workers/{chunk-YSJRB2UZ.js → chunk-FIBS5S7R.js} +2 -2
  29. package/Build/Workers/{chunk-2M7DKGLW.js → chunk-FVLVVOBQ.js} +10 -10
  30. package/Build/Workers/{chunk-B2VA6IEL.js → chunk-GL7DNVUS.js} +5 -5
  31. package/Build/Workers/{chunk-77DJBHMI.js → chunk-GPIGURCG.js} +59 -32
  32. package/Build/Workers/{chunk-QPXGGVHC.js → chunk-H2A4USJR.js} +10 -10
  33. package/Build/Workers/chunk-HSVQATK2.js +147 -0
  34. package/Build/Workers/{chunk-HXEPZWJN.js → chunk-HVMG6AG4.js} +11 -10
  35. package/Build/Workers/{chunk-H3TVRJLY.js → chunk-I3A6DXYZ.js} +4 -4
  36. package/Build/Workers/{chunk-UEWYSOFD.js → chunk-ITD2IN7N.js} +2 -2
  37. package/Build/Workers/{chunk-CYOPNGPX.js → chunk-J3OFS2RD.js} +12 -12
  38. package/Build/Workers/{chunk-RZX6LOG6.js → chunk-J647NNZW.js} +6 -6
  39. package/Build/Workers/{chunk-GLCPE2BJ.js → chunk-J7KQEKPK.js} +13 -13
  40. package/Build/Workers/{chunk-XPMXRJDD.js → chunk-K6NFIRFB.js} +5 -5
  41. package/Build/Workers/{chunk-CID5SY7L.js → chunk-LH5SF3XV.js} +7 -6
  42. package/Build/Workers/{chunk-UOQB7XQI.js → chunk-ND3NTTOF.js} +713 -435
  43. package/Build/Workers/chunk-QO2CGXMP.js +2342 -0
  44. package/Build/Workers/chunk-QSDY4NS7.js +1287 -0
  45. package/Build/Workers/chunk-QXNQQYPV.js +3201 -0
  46. package/Build/Workers/{chunk-CJ7ZDY77.js → chunk-ST2UWDUU.js} +5 -5
  47. package/Build/Workers/{chunk-YDR5LX5Z.js → chunk-TA777BGS.js} +3 -2
  48. package/Build/Workers/{chunk-U4SWB6TI.js → chunk-TAI4HLII.js} +4 -4
  49. package/Build/Workers/{chunk-VX774SWE.js → chunk-URUCCIPS.js} +6 -6
  50. package/Build/Workers/{chunk-MNSNOONX.js → chunk-VQKLRBIK.js} +7 -7
  51. package/Build/Workers/{chunk-CVAAIRNP.js → chunk-WC57YYBN.js} +2 -2
  52. package/Build/Workers/{chunk-QNABVTTP.js → chunk-WN6P5UDH.js} +12 -12
  53. package/Build/Workers/{chunk-CNLXMOPM.js → chunk-WNN5D4W3.js} +12 -11
  54. package/Build/Workers/{chunk-4JJQRZYL.js → chunk-WTQGE7Q6.js} +17 -17
  55. package/Build/Workers/{chunk-FCJQO4NC.js → chunk-WUBKZFF6.js} +2213 -1349
  56. package/Build/Workers/{chunk-3UQ2YMPP.js → chunk-ZAPOS52G.js} +12 -10
  57. package/Build/Workers/{chunk-LHFC4R7Z.js → chunk-ZCCIIBZT.js} +6 -6
  58. package/Build/Workers/combineGeometry.js +24 -24
  59. package/Build/Workers/createBoxGeometry.js +18 -18
  60. package/Build/Workers/createBoxOutlineGeometry.js +16 -16
  61. package/Build/Workers/createCircleGeometry.js +26 -26
  62. package/Build/Workers/createCircleOutlineGeometry.js +19 -19
  63. package/Build/Workers/createCoplanarPolygonGeometry.js +33 -33
  64. package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +31 -31
  65. package/Build/Workers/createCorridorGeometry.js +29 -29
  66. package/Build/Workers/createCorridorOutlineGeometry.js +28 -28
  67. package/Build/Workers/createCylinderGeometry.js +20 -20
  68. package/Build/Workers/createCylinderOutlineGeometry.js +18 -18
  69. package/Build/Workers/createEllipseGeometry.js +26 -26
  70. package/Build/Workers/createEllipseOutlineGeometry.js +19 -19
  71. package/Build/Workers/createEllipsoidGeometry.js +19 -19
  72. package/Build/Workers/createEllipsoidOutlineGeometry.js +18 -18
  73. package/Build/Workers/createFrustumGeometry.js +18 -18
  74. package/Build/Workers/createFrustumOutlineGeometry.js +18 -18
  75. package/Build/Workers/createGeometry.js +24 -24
  76. package/Build/Workers/createGroundPolylineGeometry.js +175 -118
  77. package/Build/Workers/createPlaneGeometry.js +16 -16
  78. package/Build/Workers/createPlaneOutlineGeometry.js +15 -15
  79. package/Build/Workers/createPolygonGeometry.js +32 -32
  80. package/Build/Workers/createPolygonOutlineGeometry.js +30 -30
  81. package/Build/Workers/createPolylineGeometry.js +25 -25
  82. package/Build/Workers/createPolylineVolumeGeometry.js +31 -31
  83. package/Build/Workers/createPolylineVolumeOutlineGeometry.js +27 -27
  84. package/Build/Workers/createRectangleGeometry.js +27 -27
  85. package/Build/Workers/createRectangleOutlineGeometry.js +20 -20
  86. package/Build/Workers/createSimplePolylineGeometry.js +23 -23
  87. package/Build/Workers/createSphereGeometry.js +19 -19
  88. package/Build/Workers/createSphereOutlineGeometry.js +18 -18
  89. package/Build/Workers/createTaskProcessorWorker.js +3 -3
  90. package/Build/Workers/createVectorTileClampedPolylines.js +14 -14
  91. package/Build/Workers/createVectorTileGeometries.js +24 -24
  92. package/Build/Workers/createVectorTilePoints.js +13 -13
  93. package/Build/Workers/createVectorTilePolygons.js +22 -22
  94. package/Build/Workers/createVectorTilePolylines.js +14 -14
  95. package/Build/Workers/createVerticesFromCesium3DTilesTerrain.js +25 -25
  96. package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +22 -22
  97. package/Build/Workers/createVerticesFromHeightmap.js +24 -23
  98. package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +20 -20
  99. package/Build/Workers/createWallGeometry.js +25 -25
  100. package/Build/Workers/createWallOutlineGeometry.js +24 -24
  101. package/Build/Workers/decodeDraco.js +10 -10
  102. package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +5 -5
  103. package/Build/Workers/decodeI3S.js +12 -12
  104. package/Build/Workers/gaussianSplatSorter.js +4 -4
  105. package/Build/Workers/gaussianSplatTextureGenerator.js +4 -4
  106. package/Build/Workers/incrementallyBuildTerrainPicker.js +10 -10
  107. package/Build/Workers/transcodeKTX2.js +12 -9
  108. package/Build/Workers/transferTypedArrayTest.js +1 -1
  109. package/Build/Workers/upsampleQuantizedTerrainMesh.js +22 -22
  110. package/Build/Workers/upsampleVerticesFromCesium3DTilesTerrain.js +25 -25
  111. package/Source/Core/ArcType.js +6 -1
  112. package/Source/Core/ArticulationStageType.js +5 -1
  113. package/Source/Core/AssociativeArray.js +100 -94
  114. package/Source/Core/BoundingSphere.js +1296 -1300
  115. package/Source/Core/Cartesian2.js +7 -5
  116. package/Source/Core/Cartesian3.js +9 -8
  117. package/Source/Core/Cartesian4.js +8 -6
  118. package/Source/Core/Cartographic.js +257 -249
  119. package/Source/Core/ClockRange.js +6 -1
  120. package/Source/Core/ClockStep.js +6 -1
  121. package/Source/Core/Color.js +846 -835
  122. package/Source/Core/ComponentDatatype.js +4 -1
  123. package/Source/Core/CornerType.js +6 -1
  124. package/Source/Core/Credit.js +121 -124
  125. package/Source/Core/DeveloperError.js +2 -1
  126. package/Source/Core/Ellipsoid.js +637 -660
  127. package/Source/Core/ExtrapolationType.js +6 -1
  128. package/Source/Core/GeocodeType.js +6 -1
  129. package/Source/Core/GeographicProjection.js +74 -74
  130. package/Source/Core/GeographicTilingScheme.js +179 -198
  131. package/Source/Core/GeometryOffsetAttribute.js +7 -1
  132. package/Source/Core/GeometryType.js +7 -1
  133. package/Source/Core/HeightmapEncoding.js +6 -1
  134. package/Source/Core/ITwinPlatform.js +1 -0
  135. package/Source/Core/Iau2006XysData.js +24 -13
  136. package/Source/Core/IndexDatatype.js +3 -1
  137. package/Source/Core/InterpolationType.js +5 -1
  138. package/Source/Core/Intersect.js +6 -1
  139. package/Source/Core/Ion.js +1 -1
  140. package/Source/Core/IonGeocodeProviderType.js +5 -1
  141. package/Source/Core/JulianDate.js +850 -848
  142. package/Source/Core/KeyboardEventModifier.js +6 -1
  143. package/Source/Core/MapProjection.js +39 -44
  144. package/Source/Core/Matrix2.js +906 -893
  145. package/Source/Core/Matrix3.js +1643 -1575
  146. package/Source/Core/Matrix4.js +2903 -2872
  147. package/Source/Core/PixelFormat.js +3 -1
  148. package/Source/Core/PrimitiveType.js +11 -1
  149. package/Source/Core/Ray.js +62 -60
  150. package/Source/Core/Rectangle.js +913 -904
  151. package/Source/Core/ReferenceFrame.js +6 -1
  152. package/Source/Core/RequestScheduler.js +8 -3
  153. package/Source/Core/RequestState.js +6 -1
  154. package/Source/Core/RequestType.js +6 -1
  155. package/Source/Core/S2Cell.js +2 -2
  156. package/Source/Core/ScreenSpaceEventType.js +6 -1
  157. package/Source/Core/TerrainMesh.js +10 -1
  158. package/Source/Core/TerrainPicker.js +1 -0
  159. package/Source/Core/TerrainQuantization.js +6 -1
  160. package/Source/Core/TilingScheme.js +100 -98
  161. package/Source/Core/TimeConstants.js +6 -1
  162. package/Source/Core/TimeStandard.js +6 -1
  163. package/Source/Core/TrackingReferenceFrame.js +6 -1
  164. package/Source/Core/Visibility.js +6 -1
  165. package/Source/Core/VulkanConstants.js +6 -1
  166. package/Source/Core/WallGeometry.js +1 -1
  167. package/Source/Core/WallOutlineGeometry.js +1 -1
  168. package/Source/Core/WebGLConstants.js +6 -1
  169. package/Source/Core/WebMercatorProjection.js +108 -109
  170. package/Source/Core/WebMercatorTilingScheme.js +246 -242
  171. package/Source/Core/WindingOrder.js +3 -1
  172. package/Source/Core/assert.js +27 -0
  173. package/Source/Core/globalTypes.js +4 -0
  174. package/Source/DataSources/CzmlDataSource.js +9 -0
  175. package/Source/DataSources/PathGraphics.js +13 -0
  176. package/Source/DataSources/PathVisualizer.js +330 -18
  177. package/Source/DataSources/StaticGeometryColorBatch.js +7 -2
  178. package/Source/DataSources/StaticGeometryPerMaterialBatch.js +7 -2
  179. package/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js +4 -1
  180. package/Source/DataSources/StaticGroundPolylinePerMaterialBatch.js +4 -1
  181. package/Source/DataSources/StripeOrientation.js +6 -1
  182. package/Source/Renderer/BufferUsage.js +20 -9
  183. package/Source/Renderer/Context.js +2 -29
  184. package/Source/Renderer/DrawCommand.js +435 -403
  185. package/Source/Renderer/MipmapHint.js +5 -1
  186. package/Source/Renderer/Pass.js +7 -1
  187. package/Source/Renderer/PickId.js +44 -0
  188. package/Source/Renderer/PixelDatatype.js +3 -1
  189. package/Source/Renderer/RenderState.js +2 -2
  190. package/Source/Renderer/RenderbufferFormat.js +5 -1
  191. package/Source/Renderer/ShaderDestination.js +4 -1
  192. package/Source/Renderer/TextureMagnificationFilter.js +3 -1
  193. package/Source/Renderer/TextureMinificationFilter.js +3 -1
  194. package/Source/Renderer/TextureWrap.js +5 -1
  195. package/Source/Renderer/VertexArray.js +80 -0
  196. package/Source/Scene/AlphaMode.js +5 -1
  197. package/Source/Scene/ArcGisBaseMapType.js +6 -1
  198. package/Source/Scene/ArcGisMapService.js +1 -1
  199. package/Source/Scene/AttributeType.js +3 -1
  200. package/Source/Scene/Axis.js +3 -1
  201. package/Source/Scene/BillboardCollection.js +65 -364
  202. package/Source/Scene/BingMapsStyle.js +6 -1
  203. package/Source/Scene/BlendEquation.js +6 -1
  204. package/Source/Scene/BlendFunction.js +6 -1
  205. package/Source/Scene/BlendOption.js +6 -1
  206. package/Source/Scene/BlendingState.js +6 -1
  207. package/Source/Scene/BufferLoader.js +0 -2
  208. package/Source/Scene/BufferPoint.js +148 -0
  209. package/Source/Scene/BufferPointCollection.js +138 -0
  210. package/Source/Scene/BufferPointMaterial.js +95 -0
  211. package/Source/Scene/BufferPolygon.js +516 -0
  212. package/Source/Scene/BufferPolygonCollection.js +370 -0
  213. package/Source/Scene/BufferPolygonMaterial.js +41 -0
  214. package/Source/Scene/BufferPolyline.js +185 -0
  215. package/Source/Scene/BufferPolylineCollection.js +138 -0
  216. package/Source/Scene/BufferPolylineMaterial.js +93 -0
  217. package/Source/Scene/BufferPrimitive.js +347 -0
  218. package/Source/Scene/BufferPrimitiveCollection.js +818 -0
  219. package/Source/Scene/BufferPrimitiveMaterial.js +140 -0
  220. package/Source/Scene/CameraEventType.js +6 -1
  221. package/Source/Scene/Cesium3DTileColorBlendMode.js +6 -1
  222. package/Source/Scene/Cesium3DTileContent.js +5 -1
  223. package/Source/Scene/Cesium3DTileContentFactory.js +9 -0
  224. package/Source/Scene/Cesium3DTileContentState.js +6 -1
  225. package/Source/Scene/Cesium3DTileContentType.js +3 -1
  226. package/Source/Scene/Cesium3DTileFeature.js +289 -306
  227. package/Source/Scene/Cesium3DTileOptimizationHint.js +6 -1
  228. package/Source/Scene/Cesium3DTilePass.js +5 -1
  229. package/Source/Scene/Cesium3DTilePointFeature.js +433 -511
  230. package/Source/Scene/Cesium3DTileRefine.js +6 -1
  231. package/Source/Scene/Cesium3DTileStyle.js +22 -0
  232. package/Source/Scene/Cesium3DTileVectorFeature.js +586 -0
  233. package/Source/Scene/Cesium3DTileset.js +2 -1
  234. package/Source/Scene/ClassificationType.js +3 -1
  235. package/Source/Scene/ClippingPolygonCollection.js +270 -101
  236. package/Source/Scene/CloudType.js +3 -1
  237. package/Source/Scene/ColorBlendMode.js +4 -1
  238. package/Source/Scene/CubeMapPanorama.js +4 -4
  239. package/Source/Scene/CullFace.js +6 -1
  240. package/Source/Scene/DepthFunction.js +6 -1
  241. package/Source/Scene/DynamicAtmosphereLightingType.js +3 -1
  242. package/Source/Scene/EquirectangularPanorama.js +1 -0
  243. package/Source/Scene/ExpressionNodeType.js +6 -1
  244. package/Source/Scene/GaussianSplat3DTileContent.js +40 -46
  245. package/Source/Scene/GaussianSplatPrimitive.js +413 -70
  246. package/Source/Scene/GetFeatureInfoFormat.js +3 -3
  247. package/Source/Scene/GltfBufferViewLoader.js +0 -2
  248. package/Source/Scene/GltfDracoLoader.js +0 -2
  249. package/Source/Scene/GltfImageLoader.js +0 -3
  250. package/Source/Scene/GltfIndexBufferLoader.js +0 -4
  251. package/Source/Scene/GltfJsonLoader.js +0 -2
  252. package/Source/Scene/GltfLoader.js +215 -39
  253. package/Source/Scene/GltfLoaderUtil.js +14 -0
  254. package/Source/Scene/GltfSpzLoader.js +109 -2
  255. package/Source/Scene/GltfStructuralMetadataLoader.js +0 -2
  256. package/Source/Scene/GltfTextureLoader.js +0 -2
  257. package/Source/Scene/GltfVertexBufferLoader.js +0 -4
  258. package/Source/Scene/HeightReference.js +5 -1
  259. package/Source/Scene/HorizontalOrigin.js +6 -1
  260. package/Source/Scene/ITwinData.js +1 -0
  261. package/Source/Scene/ImageryProvider.js +1 -1
  262. package/Source/Scene/ImageryState.js +6 -1
  263. package/Source/Scene/ImplicitSubdivisionScheme.js +3 -1
  264. package/Source/Scene/InstanceAttributeSemantic.js +3 -1
  265. package/Source/Scene/IonWorldImageryStyle.js +6 -1
  266. package/Source/Scene/JobType.js +6 -1
  267. package/Source/Scene/Label.js +32 -0
  268. package/Source/Scene/LabelCollection.js +14 -13
  269. package/Source/Scene/LabelStyle.js +6 -1
  270. package/Source/Scene/MapMode2D.js +6 -1
  271. package/Source/Scene/Material.js +2 -0
  272. package/Source/Scene/Megatexture.js +1 -0
  273. package/Source/Scene/MetadataClassProperty.js +24 -10
  274. package/Source/Scene/MetadataComponentType.js +118 -24
  275. package/Source/Scene/MetadataSchemaLoader.js +0 -2
  276. package/Source/Scene/MetadataSemantic.js +6 -2
  277. package/Source/Scene/MetadataType.js +3 -1
  278. package/Source/Scene/Model/B3dmLoader.js +0 -3
  279. package/Source/Scene/Model/CustomShaderMode.js +3 -1
  280. package/Source/Scene/Model/CustomShaderPipelineStage.js +3 -1
  281. package/Source/Scene/Model/CustomShaderTranslucencyMode.js +5 -1
  282. package/Source/Scene/Model/EdgeVisibilityPipelineStage.js +735 -264
  283. package/Source/Scene/Model/Extensions/Gpm/PpeSource.js +5 -1
  284. package/Source/Scene/Model/Extensions/Gpm/StorageType.js +5 -1
  285. package/Source/Scene/Model/GeoJsonLoader.js +0 -2
  286. package/Source/Scene/Model/I3dmLoader.js +0 -3
  287. package/Source/Scene/Model/InstancingPipelineStage.js +1 -1
  288. package/Source/Scene/Model/LightingModel.js +5 -1
  289. package/Source/Scene/Model/MaterialPipelineStage.js +331 -3
  290. package/Source/Scene/Model/MetadataPipelineStage.js +3 -3
  291. package/Source/Scene/Model/ModelDrawCommand.js +6 -0
  292. package/Source/Scene/Model/ModelReader.js +475 -4
  293. package/Source/Scene/Model/ModelRuntimePrimitive.js +2 -1
  294. package/Source/Scene/Model/ModelType.js +3 -1
  295. package/Source/Scene/Model/ModelUtility.js +3 -1
  296. package/Source/Scene/Model/PntsLoader.js +4 -3
  297. package/Source/Scene/Model/StyleCommandsNeeded.js +3 -1
  298. package/Source/Scene/Model/UniformType.js +5 -1
  299. package/Source/Scene/Model/VaryingType.js +5 -1
  300. package/Source/Scene/Model/createVectorTileBuffersFromModelComponents.js +375 -0
  301. package/Source/Scene/Model/pickModel.js +94 -299
  302. package/Source/Scene/ModelAnimationLoop.js +6 -1
  303. package/Source/Scene/ModelAnimationState.js +6 -1
  304. package/Source/Scene/ModelComponents.js +1639 -1542
  305. package/Source/Scene/PickedMetadataInfo.js +1 -0
  306. package/Source/Scene/PrimitiveState.js +7 -1
  307. package/Source/Scene/QuadtreeOccluders.js +20 -15
  308. package/Source/Scene/QuadtreeTile.js +547 -541
  309. package/Source/Scene/QuadtreeTileLoadState.js +6 -1
  310. package/Source/Scene/QuadtreeTileProvider.js +159 -175
  311. package/Source/Scene/ResourceLoader.js +0 -1
  312. package/Source/Scene/ResourceLoaderState.js +7 -1
  313. package/Source/Scene/SceneMode.js +4 -1
  314. package/Source/Scene/ScreenSpaceCameraController.js +13 -0
  315. package/Source/Scene/ShadowMode.js +3 -1
  316. package/Source/Scene/SkyBox.js +17 -8
  317. package/Source/Scene/SplitDirection.js +6 -1
  318. package/Source/Scene/StencilFunction.js +6 -1
  319. package/Source/Scene/StencilOperation.js +6 -1
  320. package/Source/Scene/TerrainState.js +7 -1
  321. package/Source/Scene/TileBoundingRegion.js +1 -1
  322. package/Source/Scene/TileBoundingS2Cell.js +1 -1
  323. package/Source/Scene/TileBoundingSphere.js +1 -1
  324. package/Source/Scene/TileState.js +7 -1
  325. package/Source/Scene/Tonemapper.js +5 -1
  326. package/Source/Scene/TweenCollection.js +7 -0
  327. package/Source/Scene/VectorGltf3DTileContent.js +403 -0
  328. package/Source/Scene/VertexAttributeSemantic.js +17 -1
  329. package/Source/Scene/VerticalOrigin.js +6 -1
  330. package/Source/Scene/VoxelBoxShape.js +12 -6
  331. package/Source/Scene/VoxelContent.js +2 -0
  332. package/Source/Scene/VoxelCylinderShape.js +39 -38
  333. package/Source/Scene/VoxelEllipsoidShape.js +46 -96
  334. package/Source/Scene/VoxelMetadataOrder.js +6 -1
  335. package/Source/Scene/VoxelProvider.js +1 -0
  336. package/Source/Scene/VoxelShapeType.js +3 -1
  337. package/Source/Scene/WebMapServiceImageryProvider.js +2 -2
  338. package/Source/Scene/WebMapTileServiceImageryProvider.js +366 -131
  339. package/Source/Scene/parseStructuralMetadata.js +97 -37
  340. package/Source/Scene/renderBufferPointCollection.js +285 -0
  341. package/Source/Scene/renderBufferPolygonCollection.js +339 -0
  342. package/Source/Scene/renderBufferPolylineCollection.js +478 -0
  343. package/Source/Shaders/BillboardCollectionFS.glsl +2 -77
  344. package/Source/Shaders/BillboardCollectionFS.js +2 -77
  345. package/Source/Shaders/BillboardCollectionVS.glsl +2 -60
  346. package/Source/Shaders/BillboardCollectionVS.js +2 -60
  347. package/Source/Shaders/BufferPointMaterialFS.glsl +27 -0
  348. package/Source/Shaders/BufferPointMaterialFS.js +29 -0
  349. package/Source/Shaders/BufferPointMaterialVS.glsl +48 -0
  350. package/Source/Shaders/BufferPointMaterialVS.js +50 -0
  351. package/Source/Shaders/BufferPolygonMaterialFS.glsl +13 -0
  352. package/Source/Shaders/BufferPolygonMaterialFS.js +15 -0
  353. package/Source/Shaders/BufferPolygonMaterialVS.glsl +30 -0
  354. package/Source/Shaders/BufferPolygonMaterialVS.js +32 -0
  355. package/Source/Shaders/BufferPolylineMaterialFS.glsl +13 -0
  356. package/Source/Shaders/BufferPolylineMaterialFS.js +15 -0
  357. package/Source/Shaders/BufferPolylineMaterialVS.glsl +49 -0
  358. package/Source/Shaders/BufferPolylineMaterialVS.js +51 -0
  359. package/Source/Shaders/Builtin/CzmBuiltins.js +2 -0
  360. package/Source/Shaders/Builtin/Functions/computeTextureTransform.glsl +24 -0
  361. package/Source/Shaders/Builtin/Functions/computeTextureTransform.js +25 -0
  362. package/Source/Shaders/Model/ConstantLodStageFS.glsl +60 -0
  363. package/Source/Shaders/Model/ConstantLodStageFS.js +62 -0
  364. package/Source/Shaders/Model/ConstantLodStageVS.glsl +12 -0
  365. package/Source/Shaders/Model/ConstantLodStageVS.js +13 -0
  366. package/Source/Shaders/Model/EdgeVisibilityStageFS.glsl +34 -48
  367. package/Source/Shaders/Model/EdgeVisibilityStageFS.js +34 -49
  368. package/Source/Shaders/Model/EdgeVisibilityStageVS.glsl +98 -0
  369. package/Source/Shaders/Model/EdgeVisibilityStageVS.js +100 -0
  370. package/Source/Shaders/Model/MaterialStageFS.glsl +46 -20
  371. package/Source/Shaders/Model/MaterialStageFS.js +46 -20
  372. package/Source/Shaders/Model/ModelFS.glsl +15 -0
  373. package/Source/Shaders/Model/ModelFS.js +15 -0
  374. package/Source/Shaders/Model/ModelVS.glsl +8 -0
  375. package/Source/Shaders/Model/ModelVS.js +8 -0
  376. package/Source/Shaders/PolygonSignedDistanceFS.glsl +64 -33
  377. package/Source/Shaders/PolygonSignedDistanceFS.js +64 -33
  378. package/Source/Shaders/PrimitiveGaussianSplatVS.glsl +9 -2
  379. package/Source/Shaders/PrimitiveGaussianSplatVS.js +9 -2
  380. package/Source/Shaders/Voxels/VoxelFS.glsl +1 -1
  381. package/Source/Shaders/Voxels/VoxelFS.js +1 -1
  382. package/Source/Shaders/Voxels/convertLocalToBoxUv.glsl +0 -1
  383. package/Source/Shaders/Voxels/convertLocalToBoxUv.js +0 -1
  384. package/Source/Shaders/Voxels/convertLocalToCylinderUv.glsl +7 -9
  385. package/Source/Shaders/Voxels/convertLocalToCylinderUv.js +7 -9
  386. package/Source/Shaders/Voxels/convertLocalToEllipsoidUv.glsl +7 -17
  387. package/Source/Shaders/Voxels/convertLocalToEllipsoidUv.js +7 -17
  388. package/Source/Widget/CesiumWidget.js +11 -4
  389. package/Source/Workers/decodeDraco.js +3 -0
  390. package/Source/Workers/decodeI3S.js +5 -2
  391. package/index.d.ts +1332 -402
  392. package/index.js +111 -81
  393. package/package.json +3 -3
  394. package/Build/Workers/chunk-54O3AGOA.js +0 -642
  395. package/Build/Workers/chunk-6U5QMZU3.js +0 -940
  396. package/Build/Workers/chunk-HNDE73JK.js +0 -1829
  397. package/Build/Workers/chunk-PAFMAR7A.js +0 -2357
  398. package/Build/Workers/chunk-S53HSRT6.js +0 -114
@@ -9,9 +9,11 @@ import Cartesian3 from "../../Core/Cartesian3.js";
9
9
  import Pass from "../../Renderer/Pass.js";
10
10
  import ShaderDestination from "../../Renderer/ShaderDestination.js";
11
11
  import EdgeVisibilityStageFS from "../../Shaders/Model/EdgeVisibilityStageFS.js";
12
+ import EdgeVisibilityStageVS from "../../Shaders/Model/EdgeVisibilityStageVS.js";
12
13
  import ModelUtility from "./ModelUtility.js";
13
14
  import ModelReader from "./ModelReader.js";
14
15
  import VertexAttributeSemantic from "../VertexAttributeSemantic.js";
16
+ import AttributeType from "../AttributeType.js";
15
17
 
16
18
  /**
17
19
  * Builds derived line geometry for model edges using EXT_mesh_primitive_edge_visibility data.
@@ -69,10 +71,18 @@ EdgeVisibilityPipelineStage.process = function (
69
71
  ShaderDestination.FRAGMENT,
70
72
  );
71
73
  shaderBuilder.addFragmentLines(EdgeVisibilityStageFS);
74
+ shaderBuilder.addVertexLines(EdgeVisibilityStageVS);
72
75
 
73
76
  // Add a uniform to distinguish between original geometry pass and edge pass
74
77
  shaderBuilder.addUniform("bool", "u_isEdgePass", ShaderDestination.BOTH);
75
78
 
79
+ // Add line width uniform for edge expansion if not already added by MaterialPipelineStage
80
+ const material = primitive.material;
81
+ const lineStyle = defined(material) ? material.lineStyle : undefined;
82
+ if (!defined(lineStyle) || !defined(lineStyle.width)) {
83
+ shaderBuilder.addUniform("float", "u_lineWidth", ShaderDestination.VERTEX);
84
+ }
85
+
76
86
  // Add edge type attribute and varying
77
87
  const edgeTypeLocation = shaderBuilder.addAttribute("float", "a_edgeType");
78
88
  shaderBuilder.addVarying("float", "v_edgeType", "flat");
@@ -102,23 +112,21 @@ EdgeVisibilityPipelineStage.process = function (
102
112
  shaderBuilder.addVarying("vec3", "v_faceNormalAView", "flat");
103
113
  shaderBuilder.addVarying("vec3", "v_faceNormalBView", "flat");
104
114
 
105
- // Add varying for view space position for perspective-correct silhouette detection
115
+ // Add varying for silhouette discard decision in vertex shader
116
+ shaderBuilder.addVarying("float", "v_shouldDiscard", "flat");
117
+
118
+ // Add attributes and varyings for quad-based wide line rendering
119
+ const edgeOtherPosLocation = shaderBuilder.addAttribute(
120
+ "vec3",
121
+ "a_edgeOtherPos",
122
+ );
123
+ const edgeOffsetLocation = shaderBuilder.addAttribute(
124
+ "float",
125
+ "a_edgeOffset",
126
+ );
127
+ shaderBuilder.addVarying("float", "v_edgeOffset");
106
128
 
107
- // Pass edge type, silhouette normal, and face normals from vertex to fragment shader
108
- shaderBuilder.addFunctionLines("setDynamicVaryingsVS", [
109
- "#ifdef HAS_EDGE_VISIBILITY",
110
- " if (u_isEdgePass) {",
111
- " v_edgeType = a_edgeType;",
112
- "#ifdef HAS_EDGE_FEATURE_ID",
113
- " v_featureId_0 = a_edgeFeatureId;",
114
- "#endif",
115
- " // Transform normals from model space to view space",
116
- " v_silhouetteNormalView = czm_normal * a_silhouetteNormal;",
117
- " v_faceNormalAView = czm_normal * a_faceNormalA;",
118
- " v_faceNormalBView = czm_normal * a_faceNormalB;",
119
- " }",
120
- "#endif",
121
- ]);
129
+ // Add varying for view space position for perspective-correct silhouette detection
122
130
 
123
131
  // Build triangle adjacency (mapping edges to adjacent triangles) and compute per-triangle face normals.
124
132
  const adjacencyData = buildTriangleAdjacency(primitive);
@@ -133,14 +141,56 @@ EdgeVisibilityPipelineStage.process = function (
133
141
  return;
134
142
  }
135
143
 
144
+ const runtimePrimitive = renderResources.runtimePrimitive.primitive;
145
+ const vertexColorInfo = collectVertexColors(runtimePrimitive);
146
+ const hasEdgeColorOverride = edgeResult.edgeData.some(function (edge) {
147
+ return defined(edge.color);
148
+ });
149
+
150
+ const needsEdgeColorAttribute =
151
+ hasEdgeColorOverride || defined(vertexColorInfo);
152
+
153
+ let edgeColorLocation;
154
+ if (needsEdgeColorAttribute) {
155
+ edgeColorLocation = shaderBuilder.addAttribute("vec4", "a_edgeColor");
156
+ shaderBuilder.addVarying("vec4", "v_edgeColor", "flat");
157
+ shaderBuilder.addDefine(
158
+ "HAS_EDGE_COLOR_ATTRIBUTE",
159
+ undefined,
160
+ ShaderDestination.BOTH,
161
+ );
162
+ }
163
+
164
+ let cumDistAttribute;
165
+ let edgeCumDistLocation;
166
+ const cumDistAttr = ModelUtility.getAttributeBySemantic(
167
+ primitive,
168
+ "BENTLEY_materials_line_style:CUMULATIVE_DISTANCE",
169
+ );
170
+
171
+ if (defined(cumDistAttr)) {
172
+ cumDistAttribute = cumDistAttr;
173
+ edgeCumDistLocation = shaderBuilder.addAttribute(
174
+ "float",
175
+ "a_edgeCumulativeDistance",
176
+ );
177
+ shaderBuilder.addDefine(
178
+ "HAS_EDGE_CUMULATIVE_DISTANCE",
179
+ undefined,
180
+ ShaderDestination.VERTEX,
181
+ );
182
+ }
183
+
136
184
  // Generate paired face normals for each unique edge (used to classify silhouette edges in the shader).
137
185
  const edgeFaceNormals = generateEdgeFaceNormals(
138
186
  adjacencyData,
139
187
  edgeResult.edgeIndices,
188
+ edgeResult.edgeData,
189
+ primitive.edgeVisibility,
140
190
  );
141
191
 
142
- // Create edge-domain line list geometry (2 vertices per edge) with all required attributes.
143
- const edgeGeometry = createCPULineEdgeGeometry(
192
+ // Create edge-domain quad geometry (4 vertices per edge) with all required attributes for wide line rendering.
193
+ const edgeGeometry = createQuadEdgeGeometry(
144
194
  edgeResult.edgeIndices,
145
195
  edgeResult.edgeData,
146
196
  renderResources,
@@ -150,8 +200,14 @@ EdgeVisibilityPipelineStage.process = function (
150
200
  faceNormalALocation,
151
201
  faceNormalBLocation,
152
202
  edgeFeatureIdLocation,
203
+ edgeColorLocation,
204
+ edgeOtherPosLocation,
205
+ edgeOffsetLocation,
206
+ vertexColorInfo,
153
207
  primitive.edgeVisibility,
154
208
  edgeFaceNormals,
209
+ cumDistAttribute,
210
+ edgeCumDistLocation,
155
211
  );
156
212
 
157
213
  if (!defined(edgeGeometry)) {
@@ -171,12 +227,34 @@ EdgeVisibilityPipelineStage.process = function (
171
227
  return false;
172
228
  };
173
229
 
230
+ // Provide a fallback line width when the material did not define one.
231
+ if (!defined(renderResources.uniformMap.u_lineWidth)) {
232
+ renderResources.uniformMap.u_lineWidth = function () {
233
+ return 1.0;
234
+ };
235
+ }
236
+
237
+ if (defined(cumDistAttribute)) {
238
+ if (!defined(renderResources.uniformMap.u_pixelsPerWorld)) {
239
+ renderResources.uniformMap.u_pixelsPerWorld = function () {
240
+ return 1.0;
241
+ };
242
+ }
243
+ }
244
+
245
+ const lineWidth =
246
+ defined(lineStyle) && defined(lineStyle.width)
247
+ ? lineStyle.width * frameState.pixelRatio
248
+ : undefined;
249
+
174
250
  // Store edge geometry metadata so the renderer can issue a separate edges pass.
251
+ // Use TRIANGLES instead of LINES to support wide lines via quad tessellation
175
252
  renderResources.edgeGeometry = {
176
253
  vertexArray: edgeGeometry.vertexArray,
177
254
  indexCount: edgeGeometry.indexCount,
178
- primitiveType: PrimitiveType.LINES,
255
+ primitiveType: PrimitiveType.TRIANGLES,
179
256
  pass: Pass.CESIUM_3D_TILE_EDGES,
257
+ lineWidth: lineWidth,
180
258
  };
181
259
  };
182
260
 
@@ -278,13 +356,28 @@ function buildTriangleAdjacency(primitive) {
278
356
  Cartesian3.subtract(scratchP1, scratchP0, scratchE1);
279
357
  Cartesian3.subtract(scratchP2, scratchP0, scratchE2);
280
358
  Cartesian3.cross(scratchE1, scratchE2, scratchCross);
281
- Cartesian3.normalize(scratchCross, scratchCross);
359
+
360
+ // Skip degenerate triangles: a zero or non-finite cross product cannot be
361
+ // safely normalized and would produce invalid face normals.
362
+ const crossMagnitudeSquared = Cartesian3.magnitudeSquared(scratchCross);
363
+ if (
364
+ crossMagnitudeSquared === 0.0 ||
365
+ !Number.isFinite(crossMagnitudeSquared)
366
+ ) {
367
+ continue;
368
+ }
369
+
370
+ Cartesian3.multiplyByScalar(
371
+ scratchCross,
372
+ 1.0 / Math.sqrt(crossMagnitudeSquared),
373
+ scratchCross,
374
+ );
282
375
 
283
376
  faceNormals[base] = scratchCross.x;
284
377
  faceNormals[base + 1] = scratchCross.y;
285
378
  faceNormals[base + 2] = scratchCross.z;
286
379
 
287
- // Edges
380
+ // Register edges
288
381
  processEdge(i0, i1, t);
289
382
  processEdge(i1, i2, t);
290
383
  processEdge(i2, i0, t);
@@ -294,21 +387,59 @@ function buildTriangleAdjacency(primitive) {
294
387
  }
295
388
 
296
389
  /**
297
- * For each unique edge produce a pair of face normals (A,B). For boundary edges where only a single
298
- * adjacent triangle exists, the second normal is synthesized as the negation of the first to allow
299
- * the shader to reason about front/back facing transitions uniformly.
390
+ * Generate face normal pairs for each edge. Silhouette edges use normals from the GLB
391
+ * silhouetteNormals accessor if available. Boundary edges synthesize the opposite normal
392
+ * as the negation of the first triangle's normal.
300
393
  *
301
- * @param {{edgeMap:Map<string,number[]>, faceNormals:Float32Array}} adjacencyData The adjacency data from buildTriangleAdjacency
394
+ * @param {{edgeMap:Map<string,number[]>, faceNormals:Float32Array}} adjacencyData Triangle adjacency data
302
395
  * @param {number[]} edgeIndices Packed array of 2 vertex indices per edge
396
+ * @param {Object[]} edgeData Array of edge metadata (edgeType, mateVertexIndex)
397
+ * @param {Object} edgeVisibility Edge visibility extension data
303
398
  * @returns {Float32Array} Packed array: 6 floats per edge (normalA.xyz, normalB.xyz)
304
399
  * @private
305
400
  */
306
- function generateEdgeFaceNormals(adjacencyData, edgeIndices) {
401
+ function generateEdgeFaceNormals(
402
+ adjacencyData,
403
+ edgeIndices,
404
+ edgeData,
405
+ edgeVisibility,
406
+ ) {
307
407
  const { edgeMap, faceNormals } = adjacencyData;
308
408
  const numEdges = edgeIndices.length / 2;
409
+ const edgeFaceNormals = new Float32Array(numEdges * 6);
410
+
411
+ const hasGLBSilhouetteNormals =
412
+ defined(edgeVisibility) && defined(edgeVisibility.silhouetteNormals);
413
+
414
+ // Decode GLB silhouette normals from signed-byte VEC3 to a flat Float32Array
415
+ // (3 floats per normal) to avoid per-normal object allocation and GC pressure.
416
+ let silhouetteNormalsFloat = null;
417
+
418
+ if (hasGLBSilhouetteNormals) {
419
+ const raw = edgeVisibility.silhouetteNormals;
420
+ silhouetteNormalsFloat = new Float32Array(raw.length * 3);
421
+ const scratchNormal = new Cartesian3();
422
+
423
+ for (let i = 0; i < raw.length; i++) {
424
+ const vec3 = raw[i];
425
+ // Signed byte → float: map [-128,127] → [-1,1] via [0,255]
426
+ scratchNormal.x = 2 * ((vec3.x + 128) / 255) - 1;
427
+ scratchNormal.y = 2 * ((vec3.y + 128) / 255) - 1;
428
+ scratchNormal.z = 2 * ((vec3.z + 128) / 255) - 1;
429
+
430
+ if (Cartesian3.magnitudeSquared(scratchNormal) > 0) {
431
+ Cartesian3.normalize(scratchNormal, scratchNormal);
432
+ } else {
433
+ scratchNormal.x = 0;
434
+ scratchNormal.y = 0;
435
+ scratchNormal.z = 1;
436
+ }
309
437
 
310
- // Each edge needs 2 face normals (left and right side)
311
- const edgeFaceNormals = new Float32Array(numEdges * 6); // 2 normals * 3 components each
438
+ silhouetteNormalsFloat[i * 3] = scratchNormal.x;
439
+ silhouetteNormalsFloat[i * 3 + 1] = scratchNormal.y;
440
+ silhouetteNormalsFloat[i * 3 + 2] = scratchNormal.z;
441
+ }
442
+ }
312
443
 
313
444
  for (let i = 0; i < numEdges; i++) {
314
445
  const a = edgeIndices[i * 2];
@@ -316,31 +447,61 @@ function generateEdgeFaceNormals(adjacencyData, edgeIndices) {
316
447
  const edgeKey = `${a < b ? a : b},${a < b ? b : a}`;
317
448
  const triangleList = edgeMap.get(edgeKey);
318
449
 
319
- // Expect at least one triangle; silently skip if not found (defensive)
320
- if (!defined(triangleList) || triangleList.length === 0) {
321
- continue;
450
+ const { edgeType, mateVertexIndex } = edgeData[i];
451
+
452
+ let nAx, nAy, nAz, nBx, nBy, nBz;
453
+ let usedGLBNormals = false;
454
+
455
+ // Use GLB silhouetteNormals for type=1 (SILHOUETTE) edges if available
456
+ if (
457
+ hasGLBSilhouetteNormals &&
458
+ silhouetteNormalsFloat &&
459
+ edgeType === 1 &&
460
+ mateVertexIndex >= 0
461
+ ) {
462
+ const pairBase = mateVertexIndex * 2;
463
+ if ((pairBase + 1) * 3 + 2 < silhouetteNormalsFloat.length) {
464
+ const baseA = pairBase * 3;
465
+ const baseB = (pairBase + 1) * 3;
466
+
467
+ nAx = silhouetteNormalsFloat[baseA];
468
+ nAy = silhouetteNormalsFloat[baseA + 1];
469
+ nAz = silhouetteNormalsFloat[baseA + 2];
470
+ nBx = silhouetteNormalsFloat[baseB];
471
+ nBy = silhouetteNormalsFloat[baseB + 1];
472
+ nBz = silhouetteNormalsFloat[baseB + 2];
473
+
474
+ usedGLBNormals = true;
475
+ }
322
476
  }
323
477
 
324
- const tA = triangleList[0];
325
- const aBase = tA * 3;
326
- const nAx = faceNormals[aBase];
327
- const nAy = faceNormals[aBase + 1];
328
- const nAz = faceNormals[aBase + 2];
329
-
330
- let nBx;
331
- let nBy;
332
- let nBz;
333
- if (triangleList.length > 1) {
334
- const tB = triangleList[1];
335
- const bBase = tB * 3;
336
- nBx = faceNormals[bBase];
337
- nBy = faceNormals[bBase + 1];
338
- nBz = faceNormals[bBase + 2];
339
- } else {
340
- // Boundary edge – synthesize opposite normal
341
- nBx = -nAx;
342
- nBy = -nAy;
343
- nBz = -nAz;
478
+ // Fallback to triangle adjacency if GLB normals not used
479
+ if (!usedGLBNormals) {
480
+ // Expect at least one triangle; silently skip if not found (defensive)
481
+ if (!defined(triangleList) || triangleList.length === 0) {
482
+ continue;
483
+ }
484
+
485
+ const tA = triangleList[0];
486
+ const aBase = tA * 3;
487
+ nAx = faceNormals[aBase];
488
+ nAy = faceNormals[aBase + 1];
489
+ nAz = faceNormals[aBase + 2];
490
+
491
+ const isManifold = triangleList.length > 1;
492
+
493
+ if (isManifold) {
494
+ const tB = triangleList[1];
495
+ const bBase = tB * 3;
496
+ nBx = faceNormals[bBase];
497
+ nBy = faceNormals[bBase + 1];
498
+ nBz = faceNormals[bBase + 2];
499
+ } else {
500
+ // Boundary edge – synthesize opposite normal
501
+ nBx = -nAx;
502
+ nBy = -nAy;
503
+ nBz = -nAz;
504
+ }
344
505
  }
345
506
 
346
507
  const baseIdx = i * 6;
@@ -372,91 +533,167 @@ function generateEdgeFaceNormals(adjacencyData, edgeIndices) {
372
533
  */
373
534
  function extractVisibleEdges(primitive) {
374
535
  const edgeVisibility = primitive.edgeVisibility;
536
+ if (!defined(edgeVisibility)) {
537
+ return [];
538
+ }
539
+
375
540
  const visibility = edgeVisibility.visibility;
376
541
  const indices = primitive.indices;
542
+ const lineStrings = edgeVisibility.lineStrings;
377
543
 
378
- if (!defined(visibility) || !defined(indices)) {
544
+ const attributes = primitive.attributes;
545
+ const vertexCount =
546
+ defined(attributes) && attributes.length > 0 ? attributes[0].count : 0;
547
+
548
+ const hasVisibilityData =
549
+ defined(visibility) &&
550
+ defined(indices) &&
551
+ defined(indices.typedArray) &&
552
+ indices.typedArray.length > 0;
553
+ const hasLineStrings = defined(lineStrings) && lineStrings.length > 0;
554
+
555
+ if (!hasVisibilityData && !hasLineStrings) {
379
556
  return [];
380
557
  }
381
558
 
382
- const triangleIndexArray = indices.typedArray;
383
- const vertexCount = primitive.attributes[0].count;
559
+ const triangleIndexArray = hasVisibilityData ? indices.typedArray : undefined;
384
560
  const edgeIndices = [];
385
561
  const edgeData = [];
386
562
  const seenEdgeHashes = new Set();
387
563
  let silhouetteEdgeCount = 0;
564
+ const globalColor = edgeVisibility.materialColor;
565
+
566
+ if (hasVisibilityData) {
567
+ let edgeIndex = 0;
568
+ const totalIndices = triangleIndexArray.length;
569
+ const visibilityArray = visibility;
570
+
571
+ for (let i = 0; i + 2 < totalIndices; i += 3) {
572
+ const v0 = triangleIndexArray[i];
573
+ const v1 = triangleIndexArray[i + 1];
574
+ const v2 = triangleIndexArray[i + 2];
575
+ for (let e = 0; e < 3; e++) {
576
+ let a;
577
+ let b;
578
+ if (e === 0) {
579
+ a = v0;
580
+ b = v1;
581
+ } else if (e === 1) {
582
+ a = v1;
583
+ b = v2;
584
+ } else {
585
+ a = v2;
586
+ b = v0;
587
+ }
388
588
 
389
- // Process triangles and extract edges (2 bits per edge)
390
- let edgeIndex = 0;
391
- const totalIndices = triangleIndexArray.length;
392
-
393
- for (let i = 0; i + 2 < totalIndices; i += 3) {
394
- const v0 = triangleIndexArray[i];
395
- const v1 = triangleIndexArray[i + 1];
396
- const v2 = triangleIndexArray[i + 2];
397
- for (let e = 0; e < 3; e++) {
398
- let a, b;
399
- if (e === 0) {
400
- a = v0;
401
- b = v1;
402
- } else if (e === 1) {
403
- a = v1;
404
- b = v2;
405
- } else if (e === 2) {
406
- a = v2;
407
- b = v0;
408
- }
409
- const byteIndex = Math.floor(edgeIndex / 4);
410
- const bitPairOffset = (edgeIndex % 4) * 2;
411
- edgeIndex++;
589
+ const byteIndex = Math.floor(edgeIndex / 4);
590
+ const bitPairOffset = (edgeIndex % 4) * 2;
591
+ edgeIndex++;
412
592
 
413
- if (byteIndex >= visibility.length) {
414
- break;
415
- }
593
+ if (byteIndex >= visibilityArray.length) {
594
+ break;
595
+ }
416
596
 
417
- const byte = visibility[byteIndex];
418
- const visibility2Bit = (byte >> bitPairOffset) & 0x3;
597
+ const byte = visibilityArray[byteIndex];
598
+ const visibility2Bit = (byte >> bitPairOffset) & 0x3;
419
599
 
420
- // Only include visible edge types according to EXT_mesh_primitive_edge_visibility spec
421
- let shouldIncludeEdge = false;
422
- switch (visibility2Bit) {
423
- case 0: // HIDDEN - never draw
424
- shouldIncludeEdge = false;
425
- break;
426
- case 1: // SILHOUETTE - conditionally visible (front-facing vs back-facing)
427
- shouldIncludeEdge = true;
428
- break;
429
- case 2: // HARD - always draw (primary encoding)
430
- shouldIncludeEdge = true;
431
- break;
432
- case 3: // REPEATED - always draw (secondary encoding of a hard edge already encoded as 2)
433
- shouldIncludeEdge = true;
434
- break;
435
- }
600
+ if (visibility2Bit === 0) {
601
+ continue;
602
+ }
436
603
 
437
- if (shouldIncludeEdge) {
438
604
  const small = Math.min(a, b);
439
605
  const big = Math.max(a, b);
440
- const hash = small * vertexCount + big;
606
+ const edgeKey = `${small},${big}`;
441
607
 
442
- if (!seenEdgeHashes.has(hash)) {
443
- seenEdgeHashes.add(hash);
444
- edgeIndices.push(a, b);
608
+ if (seenEdgeHashes.has(edgeKey)) {
609
+ continue;
610
+ }
611
+ seenEdgeHashes.add(edgeKey);
612
+ edgeIndices.push(a, b);
613
+
614
+ // Only process silhouette edges (type=1) as marked in GLB
615
+ // Use computed edge index for boundary edges
616
+ let mateVertexIndex = -1;
617
+ if (visibility2Bit === 1) {
618
+ mateVertexIndex = silhouetteEdgeCount;
619
+ silhouetteEdgeCount++;
620
+ }
445
621
 
446
- let mateVertexIndex = -1;
447
- if (visibility2Bit === 1) {
448
- mateVertexIndex = silhouetteEdgeCount;
449
- silhouetteEdgeCount++;
450
- }
622
+ edgeData.push({
623
+ edgeType: visibility2Bit, // Use original GLB edge type
624
+ triangleIndex: Math.floor(i / 3),
625
+ edgeIndex: e,
626
+ mateVertexIndex: mateVertexIndex,
627
+ currentTriangleVertices: [v0, v1, v2],
628
+ color: globalColor,
629
+ });
630
+ }
631
+ }
632
+ }
633
+
634
+ if (hasLineStrings) {
635
+ for (let i = 0; i < lineStrings.length; i++) {
636
+ const lineString = lineStrings[i];
637
+ if (!defined(lineString) || !defined(lineString.indices)) {
638
+ continue;
639
+ }
451
640
 
452
- edgeData.push({
453
- edgeType: visibility2Bit,
454
- triangleIndex: Math.floor(i / 3),
455
- edgeIndex: e,
456
- mateVertexIndex: mateVertexIndex,
457
- currentTriangleVertices: [v0, v1, v2],
458
- });
641
+ const indicesArray = lineString.indices;
642
+ if (!defined(indicesArray) || indicesArray.length < 2) {
643
+ continue;
644
+ }
645
+
646
+ const restartValue = lineString.restartIndex;
647
+ const lineColor = defined(lineString.materialColor)
648
+ ? lineString.materialColor
649
+ : globalColor;
650
+
651
+ let previous;
652
+ for (let j = 0; j < indicesArray.length; j++) {
653
+ const currentIndex = indicesArray[j];
654
+ if (defined(restartValue) && currentIndex === restartValue) {
655
+ previous = undefined;
656
+ continue;
657
+ }
658
+
659
+ if (!defined(previous)) {
660
+ previous = currentIndex;
661
+ continue;
662
+ }
663
+
664
+ const a = previous;
665
+ const b = currentIndex;
666
+ previous = currentIndex;
667
+
668
+ if (a === b) {
669
+ continue;
670
+ }
671
+
672
+ if (
673
+ vertexCount > 0 &&
674
+ (a < 0 || a >= vertexCount || b < 0 || b >= vertexCount)
675
+ ) {
676
+ continue;
677
+ }
678
+
679
+ const small = Math.min(a, b);
680
+ const big = Math.max(a, b);
681
+ const edgeKey = `${small},${big}`;
682
+
683
+ if (seenEdgeHashes.has(edgeKey)) {
684
+ continue;
459
685
  }
686
+
687
+ seenEdgeHashes.add(edgeKey);
688
+ edgeIndices.push(a, b);
689
+ edgeData.push({
690
+ edgeType: 2,
691
+ triangleIndex: -1,
692
+ edgeIndex: -1,
693
+ mateVertexIndex: -1,
694
+ currentTriangleVertices: undefined,
695
+ color: defined(lineColor) ? lineColor : undefined,
696
+ });
460
697
  }
461
698
  }
462
699
  }
@@ -464,10 +701,91 @@ function extractVisibleEdges(primitive) {
464
701
  return { edgeIndices, edgeData, silhouetteEdgeCount };
465
702
  }
466
703
 
704
+ function collectVertexColors(runtimePrimitive) {
705
+ if (!defined(runtimePrimitive)) {
706
+ return undefined;
707
+ }
708
+
709
+ const colorAttribute = ModelUtility.getAttributeBySemantic(
710
+ runtimePrimitive,
711
+ VertexAttributeSemantic.COLOR,
712
+ );
713
+ if (!defined(colorAttribute)) {
714
+ return undefined;
715
+ }
716
+
717
+ const components = AttributeType.getNumberOfComponents(colorAttribute.type);
718
+ if (components !== 3 && components !== 4) {
719
+ return undefined;
720
+ }
721
+
722
+ let colorData = colorAttribute.typedArray;
723
+ if (!defined(colorData)) {
724
+ colorData = ModelReader.readAttributeAsTypedArray(colorAttribute);
725
+ }
726
+ if (!defined(colorData)) {
727
+ return undefined;
728
+ }
729
+ const count = colorAttribute.count;
730
+ if (!defined(count) || count === 0) {
731
+ return undefined;
732
+ }
733
+
734
+ if (colorData.length < count * components) {
735
+ return undefined;
736
+ }
737
+
738
+ const isFloatArray =
739
+ colorData instanceof Float32Array || colorData instanceof Float64Array;
740
+ const isUint8Array = colorData instanceof Uint8Array;
741
+ const isUint16Array = colorData instanceof Uint16Array;
742
+
743
+ if (!isFloatArray && !isUint8Array && !isUint16Array) {
744
+ return undefined;
745
+ }
746
+
747
+ const colors = new Float32Array(count * 4);
748
+
749
+ const convertComponent = function (value) {
750
+ let converted;
751
+ if (isFloatArray) {
752
+ converted = value;
753
+ } else if (isUint8Array) {
754
+ converted = value / 255.0;
755
+ } else if (isUint16Array) {
756
+ converted = value / 65535.0;
757
+ }
758
+ return Math.min(Math.max(converted, 0.0), 1.0);
759
+ };
760
+
761
+ for (let i = 0; i < count; i++) {
762
+ const srcBase = i * components;
763
+ const destBase = i * 4;
764
+ colors[destBase] = convertComponent(colorData[srcBase]);
765
+ colors[destBase + 1] = convertComponent(colorData[srcBase + 1]);
766
+ colors[destBase + 2] = convertComponent(colorData[srcBase + 2]);
767
+ if (components === 4) {
768
+ colors[destBase + 3] = convertComponent(colorData[srcBase + 3]);
769
+ } else {
770
+ colors[destBase + 3] = 1.0;
771
+ }
772
+ }
773
+
774
+ return {
775
+ colors: colors,
776
+ count: count,
777
+ };
778
+ }
779
+
780
+ /**
781
+ * @typedef {object} VertexColorInfo
782
+ * @property {Float32Array} colors The packed per-vertex colors.
783
+ * @property {number} count The number of vertices.
784
+ */
785
+
467
786
  /**
468
- * Create a derived line list geometry representing edges. A new vertex domain is used so we can pack
469
- * per-edge attributes (silhouette normal, face normal pair, edge type, optional feature ID) without
470
- * modifying or duplicating the original triangle mesh. Two vertices are generated per unique edge.
787
+ * Create quad-based edge geometry for wide line rendering. Each edge becomes a quad (4 vertices, 2 triangles).
788
+ * This allows proper line width rendering in the vertex shader by extruding perpendicular to the line direction.
471
789
  *
472
790
  * @param {number[]} edgeIndices Packed array [a0,b0, a1,b1, ...] of vertex indices into the source mesh
473
791
  * @param {Object[]} edgeData Array of edge metadata including edge type and silhouette normal lookup index
@@ -478,12 +796,18 @@ function extractVisibleEdges(primitive) {
478
796
  * @param {number} faceNormalALocation Shader attribute location for face normal A
479
797
  * @param {number} faceNormalBLocation Shader attribute location for face normal B
480
798
  * @param {number} edgeFeatureIdLocation Shader attribute location for optional edge feature ID
799
+ * @param {number} edgeColorLocation Shader attribute location for optional edge color data
800
+ * @param {number} edgeOtherPosLocation Shader attribute location for the other endpoint position
801
+ * @param {number} edgeOffsetLocation Shader attribute location for edge offset (-1 or +1)
802
+ * @param {VertexColorInfo} [vertexColorInfo] Packed per-vertex colors (optional)
481
803
  * @param {Object} edgeVisibility Edge visibility extension object (may contain silhouetteNormals[])
482
804
  * @param {Float32Array} edgeFaceNormals Packed face normals (6 floats per edge)
483
- * @returns {Object|undefined} Object with {vertexArray, indexBuffer, indexCount} or undefined on failure
805
+ * @param {Object} [cumDistAttribute] Cumulative distance attribute
806
+ * @param {number} [edgeCumDistLocation] Cumulative distance location
807
+ * @returns {Object|undefined} Object with {vertexArray, indexCount, hasEdgeFeatureIds} or undefined on failure
484
808
  * @private
485
809
  */
486
- function createCPULineEdgeGeometry(
810
+ function createQuadEdgeGeometry(
487
811
  edgeIndices,
488
812
  edgeData,
489
813
  renderResources,
@@ -493,18 +817,24 @@ function createCPULineEdgeGeometry(
493
817
  faceNormalALocation,
494
818
  faceNormalBLocation,
495
819
  edgeFeatureIdLocation,
820
+ edgeColorLocation,
821
+ edgeOtherPosLocation,
822
+ edgeOffsetLocation,
823
+ vertexColorInfo,
496
824
  edgeVisibility,
497
825
  edgeFaceNormals,
826
+ cumDistAttribute,
827
+ edgeCumDistLocation,
498
828
  ) {
499
829
  if (!defined(edgeIndices) || edgeIndices.length === 0) {
500
830
  return undefined;
501
831
  }
502
832
 
503
833
  const numEdges = edgeData.length;
504
- const vertsPerEdge = 2;
834
+ const vertsPerEdge = 4; // Each edge becomes a quad (4 vertices)
505
835
  const totalVerts = numEdges * vertsPerEdge;
506
836
 
507
- // Always use location 0 for position to avoid conflicts
837
+ // Always use location 0 for position
508
838
  const positionLocation = 0;
509
839
 
510
840
  // Get original vertex positions
@@ -516,57 +846,85 @@ function createCPULineEdgeGeometry(
516
846
  ? positionAttribute.typedArray
517
847
  : ModelReader.readAttributeAsTypedArray(positionAttribute);
518
848
 
519
- // Create edge-domain vertices (2 per edge)
849
+ // Create arrays for quad vertices
520
850
  const edgePosArray = new Float32Array(totalVerts * 3);
521
851
  const edgeTypeArray = new Float32Array(totalVerts);
522
852
  const silhouetteNormalArray = new Float32Array(totalVerts * 3);
523
853
  const faceNormalAArray = new Float32Array(totalVerts * 3);
524
854
  const faceNormalBArray = new Float32Array(totalVerts * 3);
525
- let p = 0;
855
+ const edgeOtherPosArray = new Float32Array(totalVerts * 3);
856
+ const edgeOffsetArray = new Float32Array(totalVerts);
857
+
858
+ const needsCumulativeDistance = defined(cumDistAttribute);
859
+ const edgeCumDistArray = needsCumulativeDistance
860
+ ? new Float32Array(totalVerts)
861
+ : undefined;
862
+ let srcCumDist;
863
+ if (needsCumulativeDistance) {
864
+ srcCumDist = defined(cumDistAttribute.typedArray)
865
+ ? cumDistAttribute.typedArray
866
+ : ModelReader.readAttributeAsTypedArray(cumDistAttribute);
867
+ }
526
868
 
527
- const maxSrcVertex = srcPos.length / 3 - 1;
869
+ const needsEdgeColorAttribute = defined(edgeColorLocation);
870
+ const edgeColorArray = needsEdgeColorAttribute
871
+ ? new Float32Array(totalVerts * 4)
872
+ : undefined;
873
+ const vertexColors = defined(vertexColorInfo)
874
+ ? vertexColorInfo.colors
875
+ : undefined;
876
+ const vertexColorCount = defined(vertexColorInfo) ? vertexColorInfo.count : 0;
877
+
878
+ function setNoColor(destVertexIndex) {
879
+ if (!needsEdgeColorAttribute) {
880
+ return;
881
+ }
882
+ const destOffset = destVertexIndex * 4;
883
+ edgeColorArray[destOffset] = 0.0;
884
+ edgeColorArray[destOffset + 1] = 0.0;
885
+ edgeColorArray[destOffset + 2] = 0.0;
886
+ edgeColorArray[destOffset + 3] = -1.0;
887
+ }
888
+
889
+ function setColorFromOverride(destVertexIndex, color) {
890
+ if (!needsEdgeColorAttribute) {
891
+ return;
892
+ }
893
+ const destOffset = destVertexIndex * 4;
894
+ const r = defined(color.x) ? color.x : color[0];
895
+ const g = defined(color.y) ? color.y : color[1];
896
+ const b = defined(color.z) ? color.z : color[2];
897
+ const a = defined(color.w) ? color.w : defined(color[3]) ? color[3] : 1.0;
898
+ edgeColorArray[destOffset] = r;
899
+ edgeColorArray[destOffset + 1] = g;
900
+ edgeColorArray[destOffset + 2] = b;
901
+ edgeColorArray[destOffset + 3] = a;
902
+ }
528
903
 
904
+ function assignVertexColor(destVertexIndex, srcVertexIndex) {
905
+ if (!needsEdgeColorAttribute) {
906
+ return;
907
+ }
908
+ if (srcVertexIndex >= vertexColorCount) {
909
+ setNoColor(destVertexIndex);
910
+ return;
911
+ }
912
+ const srcOffset = srcVertexIndex * 4;
913
+ const destOffset = destVertexIndex * 4;
914
+ edgeColorArray[destOffset] = vertexColors[srcOffset];
915
+ edgeColorArray[destOffset + 1] = vertexColors[srcOffset + 1];
916
+ edgeColorArray[destOffset + 2] = vertexColors[srcOffset + 2];
917
+ edgeColorArray[destOffset + 3] = vertexColors[srcOffset + 3];
918
+ }
919
+
920
+ // Generate quad vertices for each edge
529
921
  for (let i = 0; i < numEdges; i++) {
530
922
  const a = edgeIndices[i * 2];
531
923
  const b = edgeIndices[i * 2 + 1];
924
+ const rawType = edgeData[i].edgeType;
925
+ const normalizedType = rawType / 255.0;
532
926
 
533
- // Validate vertex indices
534
- if (a < 0 || b < 0 || a > maxSrcVertex || b > maxSrcVertex) {
535
- // Fill with zeros to maintain indexing
536
- edgePosArray[p++] = 0;
537
- edgePosArray[p++] = 0;
538
- edgePosArray[p++] = 0;
539
- edgePosArray[p++] = 0;
540
- edgePosArray[p++] = 0;
541
- edgePosArray[p++] = 0;
542
- edgeTypeArray[i * 2] = 0;
543
- edgeTypeArray[i * 2 + 1] = 0;
544
- // Fill with default values
545
- const normalIdx = i * 2;
546
- silhouetteNormalArray[normalIdx * 3] = 0;
547
- silhouetteNormalArray[normalIdx * 3 + 1] = 0;
548
- silhouetteNormalArray[normalIdx * 3 + 2] = 1;
549
- silhouetteNormalArray[(normalIdx + 1) * 3] = 0;
550
- silhouetteNormalArray[(normalIdx + 1) * 3 + 1] = 0;
551
- silhouetteNormalArray[(normalIdx + 1) * 3 + 2] = 1;
552
-
553
- // Fill face normals with default values
554
- faceNormalAArray[normalIdx * 3] = 0;
555
- faceNormalAArray[normalIdx * 3 + 1] = 0;
556
- faceNormalAArray[normalIdx * 3 + 2] = 1;
557
- faceNormalAArray[(normalIdx + 1) * 3] = 0;
558
- faceNormalAArray[(normalIdx + 1) * 3 + 1] = 0;
559
- faceNormalAArray[(normalIdx + 1) * 3 + 2] = 1;
560
-
561
- faceNormalBArray[normalIdx * 3] = 0;
562
- faceNormalBArray[normalIdx * 3 + 1] = 0;
563
- faceNormalBArray[normalIdx * 3 + 2] = 1;
564
- faceNormalBArray[(normalIdx + 1) * 3] = 0;
565
- faceNormalBArray[(normalIdx + 1) * 3 + 1] = 0;
566
- faceNormalBArray[(normalIdx + 1) * 3 + 2] = 1;
567
- continue;
568
- }
569
-
927
+ // Get positions
570
928
  const ax = srcPos[a * 3];
571
929
  const ay = srcPos[a * 3 + 1];
572
930
  const az = srcPos[a * 3 + 2];
@@ -574,24 +932,80 @@ function createCPULineEdgeGeometry(
574
932
  const by = srcPos[b * 3 + 1];
575
933
  const bz = srcPos[b * 3 + 2];
576
934
 
577
- // Add edge endpoints
578
- edgePosArray[p++] = ax;
579
- edgePosArray[p++] = ay;
580
- edgePosArray[p++] = az;
581
- edgePosArray[p++] = bx;
582
- edgePosArray[p++] = by;
583
- edgePosArray[p++] = bz;
584
-
585
- const rawType = edgeData[i].edgeType;
586
- const t = rawType / 255.0;
935
+ // Create 4 vertices for this edge: (A-, A+, B+, B-)
936
+ // where +/- indicates offset perpendicular to the line
937
+ // Store the other endpoint position for each vertex
938
+ const baseVertexIndex = i * 4;
939
+
940
+ // Vertex 0: position at A, other endpoint is B, offset -1
941
+ edgePosArray[baseVertexIndex * 3] = ax;
942
+ edgePosArray[baseVertexIndex * 3 + 1] = ay;
943
+ edgePosArray[baseVertexIndex * 3 + 2] = az;
944
+ edgeOtherPosArray[baseVertexIndex * 3] = bx;
945
+ edgeOtherPosArray[baseVertexIndex * 3 + 1] = by;
946
+ edgeOtherPosArray[baseVertexIndex * 3 + 2] = bz;
947
+ edgeOffsetArray[baseVertexIndex] = -1.0;
948
+ edgeTypeArray[baseVertexIndex] = normalizedType;
949
+
950
+ // Vertex 1: position at A, other endpoint is B, offset +1
951
+ edgePosArray[(baseVertexIndex + 1) * 3] = ax;
952
+ edgePosArray[(baseVertexIndex + 1) * 3 + 1] = ay;
953
+ edgePosArray[(baseVertexIndex + 1) * 3 + 2] = az;
954
+ edgeOtherPosArray[(baseVertexIndex + 1) * 3] = bx;
955
+ edgeOtherPosArray[(baseVertexIndex + 1) * 3 + 1] = by;
956
+ edgeOtherPosArray[(baseVertexIndex + 1) * 3 + 2] = bz;
957
+ edgeOffsetArray[baseVertexIndex + 1] = 1.0;
958
+ edgeTypeArray[baseVertexIndex + 1] = normalizedType;
959
+
960
+ // Vertex 2: position at B, other endpoint is A, offset +1
961
+ edgePosArray[(baseVertexIndex + 2) * 3] = bx;
962
+ edgePosArray[(baseVertexIndex + 2) * 3 + 1] = by;
963
+ edgePosArray[(baseVertexIndex + 2) * 3 + 2] = bz;
964
+ edgeOtherPosArray[(baseVertexIndex + 2) * 3] = ax;
965
+ edgeOtherPosArray[(baseVertexIndex + 2) * 3 + 1] = ay;
966
+ edgeOtherPosArray[(baseVertexIndex + 2) * 3 + 2] = az;
967
+ edgeOffsetArray[baseVertexIndex + 2] = 1.0;
968
+ edgeTypeArray[baseVertexIndex + 2] = normalizedType;
969
+
970
+ // Vertex 3: position at B, other endpoint is A, offset -1
971
+ edgePosArray[(baseVertexIndex + 3) * 3] = bx;
972
+ edgePosArray[(baseVertexIndex + 3) * 3 + 1] = by;
973
+ edgePosArray[(baseVertexIndex + 3) * 3 + 2] = bz;
974
+ edgeOtherPosArray[(baseVertexIndex + 3) * 3] = ax;
975
+ edgeOtherPosArray[(baseVertexIndex + 3) * 3 + 1] = ay;
976
+ edgeOtherPosArray[(baseVertexIndex + 3) * 3 + 2] = az;
977
+ edgeOffsetArray[baseVertexIndex + 3] = -1.0;
978
+ edgeTypeArray[baseVertexIndex + 3] = normalizedType;
979
+
980
+ // Handle edge colors
981
+ const edgeOverrideColor = edgeData[i].color;
982
+ if (defined(edgeOverrideColor)) {
983
+ for (let v = 0; v < 4; v++) {
984
+ setColorFromOverride(baseVertexIndex + v, edgeOverrideColor);
985
+ }
986
+ } else if (defined(vertexColors)) {
987
+ for (let v = 0; v < 4; v++) {
988
+ assignVertexColor(baseVertexIndex + v, a);
989
+ }
990
+ } else {
991
+ for (let v = 0; v < 4; v++) {
992
+ setNoColor(baseVertexIndex + v);
993
+ }
994
+ }
587
995
 
588
- edgeTypeArray[i * 2] = t;
589
- edgeTypeArray[i * 2 + 1] = t;
996
+ if (needsCumulativeDistance) {
997
+ const cumDistA = srcCumDist[a];
998
+ const cumDistB = srcCumDist[b];
999
+ edgeCumDistArray[baseVertexIndex] = cumDistA;
1000
+ edgeCumDistArray[baseVertexIndex + 1] = cumDistA;
1001
+ edgeCumDistArray[baseVertexIndex + 2] = cumDistB;
1002
+ edgeCumDistArray[baseVertexIndex + 3] = cumDistB;
1003
+ }
590
1004
 
591
- // Add silhouette normal for silhouette edges (type 1)
1005
+ // Set silhouette normal (same for all 4 vertices)
592
1006
  let normalX = 0,
593
1007
  normalY = 0,
594
- normalZ = 1; // Default normal pointing up
1008
+ normalZ = 1;
595
1009
 
596
1010
  if (rawType === 1 && defined(edgeVisibility.silhouetteNormals)) {
597
1011
  const mateVertexIndex = edgeData[i].mateVertexIndex;
@@ -599,9 +1013,7 @@ function createCPULineEdgeGeometry(
599
1013
  mateVertexIndex >= 0 &&
600
1014
  mateVertexIndex < edgeVisibility.silhouetteNormals.length
601
1015
  ) {
602
- const silhouetteNormals = edgeVisibility.silhouetteNormals;
603
- const normal = silhouetteNormals[mateVertexIndex];
604
-
1016
+ const normal = edgeVisibility.silhouetteNormals[mateVertexIndex];
605
1017
  if (defined(normal)) {
606
1018
  normalX = normal.x;
607
1019
  normalY = normal.y;
@@ -610,17 +1022,14 @@ function createCPULineEdgeGeometry(
610
1022
  }
611
1023
  }
612
1024
 
613
- // Set silhouette normal for both edge endpoints
614
- const normalIdx = i * 2;
615
- silhouetteNormalArray[normalIdx * 3] = normalX;
616
- silhouetteNormalArray[normalIdx * 3 + 1] = normalY;
617
- silhouetteNormalArray[normalIdx * 3 + 2] = normalZ;
618
- silhouetteNormalArray[(normalIdx + 1) * 3] = normalX;
619
- silhouetteNormalArray[(normalIdx + 1) * 3 + 1] = normalY;
620
- silhouetteNormalArray[(normalIdx + 1) * 3 + 2] = normalZ;
621
-
622
- // Set face normals for both edge endpoints
623
- const faceNormalIdx = i * 6; // 6 floats per edge (2 normals * 3 components)
1025
+ for (let v = 0; v < 4; v++) {
1026
+ silhouetteNormalArray[(baseVertexIndex + v) * 3] = normalX;
1027
+ silhouetteNormalArray[(baseVertexIndex + v) * 3 + 1] = normalY;
1028
+ silhouetteNormalArray[(baseVertexIndex + v) * 3 + 2] = normalZ;
1029
+ }
1030
+
1031
+ // Set face normals (same for all 4 vertices)
1032
+ const faceNormalIdx = i * 6;
624
1033
  const normalAX = edgeFaceNormals[faceNormalIdx];
625
1034
  const normalAY = edgeFaceNormals[faceNormalIdx + 1];
626
1035
  const normalAZ = edgeFaceNormals[faceNormalIdx + 2];
@@ -628,21 +1037,14 @@ function createCPULineEdgeGeometry(
628
1037
  const normalBY = edgeFaceNormals[faceNormalIdx + 4];
629
1038
  const normalBZ = edgeFaceNormals[faceNormalIdx + 5];
630
1039
 
631
- // Face normal A for both endpoints
632
- faceNormalAArray[normalIdx * 3] = normalAX;
633
- faceNormalAArray[normalIdx * 3 + 1] = normalAY;
634
- faceNormalAArray[normalIdx * 3 + 2] = normalAZ;
635
- faceNormalAArray[(normalIdx + 1) * 3] = normalAX;
636
- faceNormalAArray[(normalIdx + 1) * 3 + 1] = normalAY;
637
- faceNormalAArray[(normalIdx + 1) * 3 + 2] = normalAZ;
638
-
639
- // Face normal B for both endpoints
640
- faceNormalBArray[normalIdx * 3] = normalBX;
641
- faceNormalBArray[normalIdx * 3 + 1] = normalBY;
642
- faceNormalBArray[normalIdx * 3 + 2] = normalBZ;
643
- faceNormalBArray[(normalIdx + 1) * 3] = normalBX;
644
- faceNormalBArray[(normalIdx + 1) * 3 + 1] = normalBY;
645
- faceNormalBArray[(normalIdx + 1) * 3 + 2] = normalBZ;
1040
+ for (let v = 0; v < 4; v++) {
1041
+ faceNormalAArray[(baseVertexIndex + v) * 3] = normalAX;
1042
+ faceNormalAArray[(baseVertexIndex + v) * 3 + 1] = normalAY;
1043
+ faceNormalAArray[(baseVertexIndex + v) * 3 + 2] = normalAZ;
1044
+ faceNormalBArray[(baseVertexIndex + v) * 3] = normalBX;
1045
+ faceNormalBArray[(baseVertexIndex + v) * 3 + 1] = normalBY;
1046
+ faceNormalBArray[(baseVertexIndex + v) * 3 + 2] = normalBZ;
1047
+ }
646
1048
  }
647
1049
 
648
1050
  // Create vertex buffers
@@ -651,44 +1053,92 @@ function createCPULineEdgeGeometry(
651
1053
  typedArray: edgePosArray,
652
1054
  usage: BufferUsage.STATIC_DRAW,
653
1055
  });
1056
+
654
1057
  const edgeTypeBuffer = Buffer.createVertexBuffer({
655
1058
  context,
656
1059
  typedArray: edgeTypeArray,
657
1060
  usage: BufferUsage.STATIC_DRAW,
658
1061
  });
1062
+
659
1063
  const silhouetteNormalBuffer = Buffer.createVertexBuffer({
660
1064
  context,
661
1065
  typedArray: silhouetteNormalArray,
662
1066
  usage: BufferUsage.STATIC_DRAW,
663
1067
  });
1068
+
664
1069
  const faceNormalABuffer = Buffer.createVertexBuffer({
665
1070
  context,
666
1071
  typedArray: faceNormalAArray,
667
1072
  usage: BufferUsage.STATIC_DRAW,
668
1073
  });
1074
+
669
1075
  const faceNormalBBuffer = Buffer.createVertexBuffer({
670
1076
  context,
671
1077
  typedArray: faceNormalBArray,
672
1078
  usage: BufferUsage.STATIC_DRAW,
673
1079
  });
674
1080
 
675
- // Create sequential indices for line pairs
1081
+ const edgeOtherPosBuffer = Buffer.createVertexBuffer({
1082
+ context,
1083
+ typedArray: edgeOtherPosArray,
1084
+ usage: BufferUsage.STATIC_DRAW,
1085
+ });
1086
+
1087
+ const edgeOffsetBuffer = Buffer.createVertexBuffer({
1088
+ context,
1089
+ typedArray: edgeOffsetArray,
1090
+ usage: BufferUsage.STATIC_DRAW,
1091
+ });
1092
+
1093
+ const edgeColorBuffer = needsEdgeColorAttribute
1094
+ ? Buffer.createVertexBuffer({
1095
+ context,
1096
+ typedArray: edgeColorArray,
1097
+ usage: BufferUsage.STATIC_DRAW,
1098
+ })
1099
+ : undefined;
1100
+
1101
+ const edgeCumDistBuffer = needsCumulativeDistance
1102
+ ? Buffer.createVertexBuffer({
1103
+ context,
1104
+ typedArray: edgeCumDistArray,
1105
+ usage: BufferUsage.STATIC_DRAW,
1106
+ })
1107
+ : undefined;
1108
+
1109
+ // Create triangle indices for quads: (0,1,2, 0,2,3) for each quad
1110
+ const numTriangles = numEdges * 2;
1111
+ const numIndices = numTriangles * 3;
676
1112
  const useU32 = totalVerts > 65534;
677
- const idx = new Array(totalVerts);
678
- for (let i = 0; i < totalVerts; i++) {
679
- idx[i] = i;
1113
+ const indices = useU32
1114
+ ? new Uint32Array(numIndices)
1115
+ : new Uint16Array(numIndices);
1116
+
1117
+ for (let i = 0; i < numEdges; i++) {
1118
+ const baseVertex = i * 4;
1119
+ const baseIndex = i * 6;
1120
+
1121
+ // Triangle 1: (v0, v1, v2)
1122
+ indices[baseIndex] = baseVertex;
1123
+ indices[baseIndex + 1] = baseVertex + 1;
1124
+ indices[baseIndex + 2] = baseVertex + 2;
1125
+
1126
+ // Triangle 2: (v0, v2, v3)
1127
+ indices[baseIndex + 3] = baseVertex;
1128
+ indices[baseIndex + 4] = baseVertex + 2;
1129
+ indices[baseIndex + 5] = baseVertex + 3;
680
1130
  }
681
1131
 
682
1132
  const indexBuffer = Buffer.createIndexBuffer({
683
1133
  context,
684
- typedArray: useU32 ? new Uint32Array(idx) : new Uint16Array(idx),
1134
+ typedArray: indices,
685
1135
  usage: BufferUsage.STATIC_DRAW,
686
1136
  indexDatatype: useU32
687
1137
  ? IndexDatatype.UNSIGNED_INT
688
1138
  : IndexDatatype.UNSIGNED_SHORT,
689
1139
  });
690
1140
 
691
- // Create vertex array with position, edge type, silhouette normal, and face normal attributes
1141
+ // Create vertex array with all attributes
692
1142
  const attributes = [
693
1143
  {
694
1144
  index: positionLocation,
@@ -725,75 +1175,96 @@ function createCPULineEdgeGeometry(
725
1175
  componentDatatype: ComponentDatatype.FLOAT,
726
1176
  normalize: false,
727
1177
  },
1178
+ {
1179
+ index: edgeOtherPosLocation,
1180
+ vertexBuffer: edgeOtherPosBuffer,
1181
+ componentsPerAttribute: 3,
1182
+ componentDatatype: ComponentDatatype.FLOAT,
1183
+ normalize: false,
1184
+ },
1185
+ {
1186
+ index: edgeOffsetLocation,
1187
+ vertexBuffer: edgeOffsetBuffer,
1188
+ componentsPerAttribute: 1,
1189
+ componentDatatype: ComponentDatatype.FLOAT,
1190
+ normalize: false,
1191
+ },
728
1192
  ];
729
1193
 
730
- // Get feature ID from original geometry
731
- const primitive = renderResources.runtimePrimitive.primitive;
732
- const getFeatureIdForEdge = function () {
733
- // Try to get the first feature ID from the original primitive
734
- if (defined(primitive.featureIds) && primitive.featureIds.length > 0) {
735
- const firstFeatureIdSet = primitive.featureIds[0];
736
-
737
- // Handle FeatureIdAttribute objects directly using setIndex
738
- if (defined(firstFeatureIdSet.setIndex)) {
739
- const featureIdAttribute = primitive.attributes.find(
740
- (attr) =>
741
- attr.semantic === VertexAttributeSemantic.FEATURE_ID &&
742
- attr.setIndex === firstFeatureIdSet.setIndex,
743
- );
744
-
745
- if (defined(featureIdAttribute)) {
746
- const featureIds = defined(featureIdAttribute.typedArray)
747
- ? featureIdAttribute.typedArray
748
- : ModelReader.readAttributeAsTypedArray(featureIdAttribute);
749
-
750
- // Create edge feature ID buffer based on edge indices
751
- const edgeFeatureIds = new Float32Array(totalVerts);
752
- for (let i = 0; i < numEdges; i++) {
753
- const a = edgeIndices[i * 2];
754
- const featureId = a < featureIds.length ? featureIds[a] : 0;
755
- edgeFeatureIds[i * 2] = featureId;
756
- edgeFeatureIds[i * 2 + 1] = featureId;
757
- }
758
-
759
- return edgeFeatureIds;
760
- }
761
- }
762
- }
763
-
764
- return undefined;
765
- };
766
-
767
- const edgeFeatureIds = getFeatureIdForEdge();
768
- const hasEdgeFeatureIds = defined(edgeFeatureIds);
769
-
770
- if (hasEdgeFeatureIds) {
771
- const edgeFeatureIdBuffer = Buffer.createVertexBuffer({
772
- context,
773
- typedArray: edgeFeatureIds,
774
- usage: BufferUsage.STATIC_DRAW,
1194
+ if (needsEdgeColorAttribute) {
1195
+ attributes.push({
1196
+ index: edgeColorLocation,
1197
+ vertexBuffer: edgeColorBuffer,
1198
+ componentsPerAttribute: 4,
1199
+ componentDatatype: ComponentDatatype.FLOAT,
1200
+ normalize: false,
775
1201
  });
1202
+ }
776
1203
 
1204
+ if (needsCumulativeDistance) {
777
1205
  attributes.push({
778
- index: edgeFeatureIdLocation,
779
- vertexBuffer: edgeFeatureIdBuffer,
1206
+ index: edgeCumDistLocation,
1207
+ vertexBuffer: edgeCumDistBuffer,
780
1208
  componentsPerAttribute: 1,
781
1209
  componentDatatype: ComponentDatatype.FLOAT,
782
1210
  normalize: false,
783
1211
  });
784
1212
  }
785
1213
 
786
- const vertexArray = new VertexArray({ context, indexBuffer, attributes });
1214
+ const primitive = renderResources.runtimePrimitive.primitive;
1215
+ if (defined(primitive.featureIds) && primitive.featureIds.length > 0) {
1216
+ const firstFeatureIdSet = primitive.featureIds[0];
1217
+
1218
+ if (defined(firstFeatureIdSet.setIndex)) {
1219
+ const featureIdAttribute = primitive.attributes.find(
1220
+ (attr) =>
1221
+ attr.semantic === VertexAttributeSemantic.FEATURE_ID &&
1222
+ attr.setIndex === firstFeatureIdSet.setIndex,
1223
+ );
1224
+
1225
+ if (defined(featureIdAttribute)) {
1226
+ const featureIds = defined(featureIdAttribute.typedArray)
1227
+ ? featureIdAttribute.typedArray
1228
+ : ModelReader.readAttributeAsTypedArray(featureIdAttribute);
1229
+
1230
+ const edgeFeatureIds = new Float32Array(totalVerts);
1231
+ for (let i = 0; i < numEdges; i++) {
1232
+ const a = edgeIndices[i * 2];
1233
+ const featureId = a < featureIds.length ? featureIds[a] : 0;
1234
+ // Set same feature ID for all 4 vertices of the quad
1235
+ for (let v = 0; v < 4; v++) {
1236
+ edgeFeatureIds[i * 4 + v] = featureId;
1237
+ }
1238
+ }
787
1239
 
788
- if (!vertexArray || totalVerts === 0 || totalVerts % 2 !== 0) {
789
- return undefined;
1240
+ const edgeFeatureIdBuffer = Buffer.createVertexBuffer({
1241
+ context,
1242
+ typedArray: edgeFeatureIds,
1243
+ usage: BufferUsage.STATIC_DRAW,
1244
+ });
1245
+
1246
+ attributes.push({
1247
+ index: edgeFeatureIdLocation,
1248
+ vertexBuffer: edgeFeatureIdBuffer,
1249
+ componentsPerAttribute: 1,
1250
+ componentDatatype: ComponentDatatype.FLOAT,
1251
+ normalize: false,
1252
+ });
1253
+ }
1254
+ }
790
1255
  }
791
1256
 
1257
+ const vertexArray = new VertexArray({
1258
+ context,
1259
+ attributes,
1260
+ indexBuffer,
1261
+ });
1262
+
792
1263
  return {
793
1264
  vertexArray,
794
- indexBuffer,
795
- indexCount: totalVerts,
796
- hasEdgeFeatureIds,
1265
+ indexCount: numIndices,
1266
+ hasEdgeFeatureIds:
1267
+ defined(primitive.featureIds) && primitive.featureIds.length > 0,
797
1268
  };
798
1269
  }
799
1270