@cesium/engine 25.0.0 → 26.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 (187) hide show
  1. package/Build/Workers/{chunk-GPIGURCG.js → chunk-3VFEWOBI.js} +7 -7
  2. package/Build/Workers/{chunk-BTX2NL3P.js → chunk-424RNO3D.js} +18 -18
  3. package/Build/Workers/{chunk-HSVQATK2.js → chunk-4MGMYHOO.js} +6 -6
  4. package/Build/Workers/{chunk-FIBS5S7R.js → chunk-4S7IE3LB.js} +2 -2
  5. package/Build/Workers/{chunk-A7ZBMVFS.js → chunk-52JDLOEM.js} +14 -14
  6. package/Build/Workers/{chunk-ZCCIIBZT.js → chunk-54I6Y66F.js} +6 -6
  7. package/Build/Workers/{chunk-J647NNZW.js → chunk-6YEE6JDR.js} +6 -6
  8. package/Build/Workers/{chunk-HVMG6AG4.js → chunk-7J2HKPRH.js} +9 -9
  9. package/Build/Workers/{chunk-K6NFIRFB.js → chunk-7WM2PX4V.js} +5 -5
  10. package/Build/Workers/{chunk-3LSD7OOA.js → chunk-ACXQXN46.js} +16 -16
  11. package/Build/Workers/{chunk-CZ23Y3RM.js → chunk-AYKR4VBR.js} +2 -2
  12. package/Build/Workers/{chunk-4MTRQFJP.js → chunk-C6J67V5A.js} +1 -1
  13. package/Build/Workers/{chunk-WTQGE7Q6.js → chunk-C6KNZ7T4.js} +17 -17
  14. package/Build/Workers/{chunk-AWFZHD2B.js → chunk-CFQP6LYM.js} +4 -4
  15. package/Build/Workers/{chunk-ST2UWDUU.js → chunk-CXOYE2WM.js} +5 -5
  16. package/Build/Workers/{chunk-H2A4USJR.js → chunk-CZEYZU4N.js} +10 -10
  17. package/Build/Workers/{chunk-DFEI5MAV.js → chunk-DBOEKL43.js} +7 -7
  18. package/Build/Workers/{chunk-A7A433MD.js → chunk-DDWSZVMY.js} +5 -5
  19. package/Build/Workers/{chunk-J7KQEKPK.js → chunk-DOBXCNC3.js} +13 -13
  20. package/Build/Workers/{chunk-URUCCIPS.js → chunk-E7VQ76KE.js} +6 -6
  21. package/Build/Workers/{chunk-ZAPOS52G.js → chunk-EBSIOBXY.js} +8 -8
  22. package/Build/Workers/{chunk-3VDDRF2E.js → chunk-EF2QYXGA.js} +14 -14
  23. package/Build/Workers/{chunk-WN6P5UDH.js → chunk-EPYXRCDB.js} +12 -12
  24. package/Build/Workers/{chunk-EZARA5FJ.js → chunk-F6QDY6HU.js} +13 -13
  25. package/Build/Workers/{chunk-GL7DNVUS.js → chunk-FRQZECAO.js} +5 -5
  26. package/Build/Workers/{chunk-VQKLRBIK.js → chunk-G7PXZRVF.js} +7 -7
  27. package/Build/Workers/{chunk-4QQXGTCE.js → chunk-INUEEEQA.js} +8 -8
  28. package/Build/Workers/{chunk-ITD2IN7N.js → chunk-IRBKFCEJ.js} +2 -2
  29. package/Build/Workers/{chunk-6SDGQI27.js → chunk-IYOUHCZB.js} +1 -1
  30. package/Build/Workers/{chunk-DYT5NR6P.js → chunk-J6BWOHUF.js} +3 -3
  31. package/Build/Workers/{chunk-4GF4MVPY.js → chunk-KFSTQKNM.js} +7 -7
  32. package/Build/Workers/{chunk-4XXHJI6Y.js → chunk-KKOSKAZB.js} +17 -17
  33. package/Build/Workers/{chunk-WC57YYBN.js → chunk-KSSWJIZW.js} +2 -2
  34. package/Build/Workers/{chunk-5T6QQAJW.js → chunk-M3B5JKSM.js} +1 -1
  35. package/Build/Workers/{chunk-QO2CGXMP.js → chunk-MPZHGZU6.js} +6 -6
  36. package/Build/Workers/{chunk-WUBKZFF6.js → chunk-MYP774IS.js} +9 -9
  37. package/Build/Workers/{chunk-WNN5D4W3.js → chunk-O3EA5HS7.js} +10 -10
  38. package/Build/Workers/{chunk-77RL3MBD.js → chunk-P3CK7MCY.js} +25 -4
  39. package/Build/Workers/{chunk-QXNQQYPV.js → chunk-Q3PY526V.js} +8 -8
  40. package/Build/Workers/{chunk-CKQP3DSS.js → chunk-QN67VG36.js} +6 -6
  41. package/Build/Workers/{chunk-ACFFCHHZ.js → chunk-QRWGUWI6.js} +11 -11
  42. package/Build/Workers/{chunk-LH5SF3XV.js → chunk-S4MCOY6I.js} +5 -5
  43. package/Build/Workers/{chunk-FVLVVOBQ.js → chunk-SMQZZOW6.js} +10 -10
  44. package/Build/Workers/{chunk-TA777BGS.js → chunk-TKKIREQ6.js} +1 -1
  45. package/Build/Workers/{chunk-AEAVLYPS.js → chunk-U3ZA64U7.js} +2 -2
  46. package/Build/Workers/{chunk-7LSFAEWF.js → chunk-UA25D5MX.js} +10 -10
  47. package/Build/Workers/{chunk-J3OFS2RD.js → chunk-UOOIQ3KX.js} +12 -12
  48. package/Build/Workers/{chunk-ND3NTTOF.js → chunk-V7VQKN6N.js} +6 -6
  49. package/Build/Workers/{chunk-I3A6DXYZ.js → chunk-VQYETPWC.js} +4 -4
  50. package/Build/Workers/{chunk-35H3UBIO.js → chunk-VWV2IJRB.js} +11 -11
  51. package/Build/Workers/{chunk-QSDY4NS7.js → chunk-XZMBNNDX.js} +9 -9
  52. package/Build/Workers/{chunk-TAI4HLII.js → chunk-Y57HREW5.js} +4 -4
  53. package/Build/Workers/{chunk-3TKLDHV3.js → chunk-Y5BF6AFU.js} +2 -2
  54. package/Build/Workers/{chunk-3XY3MVPG.js → chunk-YLY7NKAB.js} +4 -4
  55. package/Build/Workers/{chunk-BVAIWR7O.js → chunk-ZK3CF7ZD.js} +12 -12
  56. package/Build/Workers/{chunk-DH26SNAB.js → chunk-ZP7JMQV4.js} +1 -1
  57. package/Build/Workers/{chunk-3RFFPH4M.js → chunk-ZZ46LWL6.js} +1 -1
  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 +22 -22
  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 +22 -22
  98. package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +20 -20
  99. package/Build/Workers/createWallGeometry.js +24 -24
  100. package/Build/Workers/createWallOutlineGeometry.js +23 -23
  101. package/Build/Workers/decodeDraco.js +10 -10
  102. package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +5 -5
  103. package/Build/Workers/decodeI3S.js +10 -10
  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 +6 -6
  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/Cartesian2.js +1 -1
  112. package/Source/Core/Cartesian3.js +1 -1
  113. package/Source/Core/Cartesian4.js +1 -1
  114. package/Source/Core/ComponentDatatype.js +35 -0
  115. package/Source/Core/Ion.js +1 -1
  116. package/Source/Core/MapProjection.js +1 -0
  117. package/Source/Core/Matrix2.js +1 -1
  118. package/Source/Core/Matrix3.js +1 -1
  119. package/Source/Core/Matrix4.js +1 -1
  120. package/Source/Core/Resource.js +1 -1
  121. package/Source/Core/ScreenSpaceEventHandler.js +51 -41
  122. package/Source/Core/createColorRamp.js +37 -0
  123. package/Source/Core/globalTypes.js +25 -0
  124. package/Source/Renderer/Pass.js +3 -2
  125. package/Source/Renderer/createUniform.js +346 -239
  126. package/Source/Renderer/createUniformArray.js +494 -381
  127. package/Source/Scene/ArcGisMapService.js +1 -1
  128. package/Source/Scene/BufferPoint.js +1 -0
  129. package/Source/Scene/BufferPointCollection.js +14 -1
  130. package/Source/Scene/BufferPolygon.js +3 -2
  131. package/Source/Scene/BufferPolygonCollection.js +10 -0
  132. package/Source/Scene/BufferPolyline.js +1 -0
  133. package/Source/Scene/BufferPolylineCollection.js +2 -0
  134. package/Source/Scene/BufferPrimitiveCollection.js +79 -28
  135. package/Source/Scene/CameraEventAggregator.js +30 -18
  136. package/Source/Scene/Cesium3DTile.js +54 -1
  137. package/Source/Scene/Cesium3DTileContent.js +195 -254
  138. package/Source/Scene/Cesium3DTileContentFactory.js +10 -2
  139. package/Source/Scene/Cesium3DTileset.js +45 -5
  140. package/Source/Scene/Composite3DTileContent.js +254 -292
  141. package/Source/Scene/EdgeDisplayMode.js +50 -0
  142. package/Source/Scene/Empty3DTileContent.js +100 -132
  143. package/Source/Scene/GaussianSplat3DTileContent.js +436 -478
  144. package/Source/Scene/GeoJsonPrimitive.js +874 -0
  145. package/Source/Scene/Geometry3DTileContent.js +151 -185
  146. package/Source/Scene/GltfLoader.js +109 -0
  147. package/Source/Scene/Implicit3DTileContent.js +179 -214
  148. package/Source/Scene/MVTDataProvider.js +147 -0
  149. package/Source/Scene/Model/EdgeVisibilityPipelineStage.js +79 -311
  150. package/Source/Scene/Model/Model.js +34 -0
  151. package/Source/Scene/Model/Model3DTileContent.js +424 -458
  152. package/Source/Scene/Model/ModelDrawCommand.js +31 -3
  153. package/Source/Scene/Model/ModelUtility.js +4 -0
  154. package/Source/Scene/Model/createVectorTileBuffersFromModelComponents.js +466 -150
  155. package/Source/Scene/ModelComponents.js +39 -1
  156. package/Source/Scene/Multiple3DTileContent.js +291 -334
  157. package/Source/Scene/Scene.js +26 -0
  158. package/Source/Scene/Tileset3DTileContent.js +113 -146
  159. package/Source/Scene/UrlTemplate3DTilesDataProvider.js +499 -0
  160. package/Source/Scene/Vector3DTileContent.js +205 -234
  161. package/Source/Scene/VectorGltf3DTileContent.js +85 -36
  162. package/Source/Scene/VoxelPrimitive.js +159 -175
  163. package/Source/Scene/VoxelProvider.js +64 -91
  164. package/Source/Scene/buildVectorGltfFromMVT.js +1059 -0
  165. package/Source/Scene/buildVoxelCustomShader.js +199 -0
  166. package/Source/Scene/decodeMVT.js +634 -0
  167. package/Source/Scene/renderBufferPointCollection.js +110 -64
  168. package/Source/Scene/renderBufferPolygonCollection.js +102 -55
  169. package/Source/Scene/renderBufferPolylineCollection.js +365 -166
  170. package/Source/Shaders/BufferPointMaterialFS.glsl +1 -0
  171. package/Source/Shaders/BufferPointMaterialFS.js +1 -0
  172. package/Source/Shaders/BufferPointMaterialVS.glsl +19 -9
  173. package/Source/Shaders/BufferPointMaterialVS.js +20 -10
  174. package/Source/Shaders/BufferPolygonMaterialVS.glsl +13 -4
  175. package/Source/Shaders/BufferPolygonMaterialVS.js +14 -5
  176. package/Source/Shaders/BufferPolylineMaterialVS.glsl +16 -2
  177. package/Source/Shaders/BufferPolylineMaterialVS.js +17 -3
  178. package/Source/Shaders/Builtin/Constants/passCesium3DTileEdgesDirect.glsl +9 -0
  179. package/Source/Shaders/Builtin/Constants/passCesium3DTileEdgesDirect.js +11 -0
  180. package/Source/Shaders/Builtin/Constants/passOverlay.glsl +1 -1
  181. package/Source/Shaders/Builtin/Constants/passOverlay.js +1 -1
  182. package/Source/Shaders/Builtin/CzmBuiltins.js +2 -0
  183. package/Source/Shaders/Model/EdgeVisibilityStageVS.glsl +0 -1
  184. package/Source/Shaders/Model/EdgeVisibilityStageVS.js +0 -1
  185. package/index.d.ts +253 -35
  186. package/index.js +71 -62
  187. package/package.json +2 -2
@@ -1,7 +1,6 @@
1
1
  // @ts-check
2
2
 
3
3
  import Cartesian3 from "../../Core/Cartesian3.js";
4
- import assert from "../../Core/assert.js";
5
4
  import defined from "../../Core/defined.js";
6
5
  import Matrix4 from "../../Core/Matrix4.js";
7
6
  import PrimitiveType from "../../Core/PrimitiveType.js";
@@ -18,17 +17,18 @@ import ModelUtility from "./ModelUtility.js";
18
17
  import ModelComponents from "../ModelComponents.js";
19
18
  import Cesium3DTileVectorFeature from "../Cesium3DTileVectorFeature.js";
20
19
 
21
- /** @import { TypedArray } from "../../Core/globalTypes.js"; */
20
+ /** @import { TypedArray, TypedArrayConstructor } from "../../Core/globalTypes.js"; */
22
21
  /** @import BufferPrimitive from "../BufferPrimitive.js"; */
23
22
  /** @import BufferPrimitiveCollection from "../BufferPrimitiveCollection.js"; */
24
23
  /** @import VectorGltf3DTileContent from "../VectorGltf3DTileContent.js"; */
25
- /** @import {Attribute, Components, Node, Primitive} from "../ModelComponents.js"; */
24
+ /** @import {Attribute, Components, Node, Polygon, Primitive, Vector} from "../ModelComponents.js"; */
26
25
 
27
26
  /**
28
27
  * @typedef {object} VectorTileResult
29
- * @property {Array<BufferPrimitiveCollection<BufferPrimitive>>} collections
30
- * @property {Array<Matrix4>} collectionLocalMatrices
31
- * @property {Map<number, Cesium3DTileVectorFeature>} features
28
+ * @property {Array<BufferPrimitiveCollection<BufferPrimitive>>} collections List of all vector primitive collections.
29
+ * @property {Array<Matrix4>} collectionLocalMatrices List of transform matrices for each collection; order matches 'collections'.
30
+ * @property {Map<BufferPrimitiveCollection<BufferPrimitive>, number>} collectionFeatureTableIds Maps vector primitive collection -> propertyTableId.
31
+ * @property {Map<number, Map<number, Cesium3DTileVectorFeature>>} featuresByTableId Maps propertyTableId -> featureId -> feature.
32
32
  * @ignore
33
33
  */
34
34
 
@@ -53,7 +53,8 @@ function createVectorTileBuffersFromModelComponents(content, components) {
53
53
  const result = {
54
54
  collections: [],
55
55
  collectionLocalMatrices: [],
56
- features: new Map(),
56
+ collectionFeatureTableIds: new Map(),
57
+ featuresByTableId: new Map(),
57
58
  };
58
59
 
59
60
  for (let i = 0; i < rootNodes.length; i++) {
@@ -72,25 +73,6 @@ function getPrimitiveRestartIndex(indices) {
72
73
  return Math.pow(2, bits) - 1;
73
74
  }
74
75
 
75
- /**
76
- * @param {TypedArray} indices
77
- * @param {Function} callback
78
- * @ignore
79
- */
80
- function forEachLineStripSegment(indices, callback) {
81
- const restart = getPrimitiveRestartIndex(indices);
82
- let segmentStart = 0;
83
- for (let i = 0; i <= indices.length; i++) {
84
- if (i === indices.length || indices[i] === restart) {
85
- const segmentCount = i - segmentStart;
86
- if (segmentCount > 0) {
87
- callback(segmentStart, segmentCount);
88
- }
89
- segmentStart = i + 1;
90
- }
91
- }
92
- }
93
-
94
76
  /**
95
77
  * @param {Primitive} primitive
96
78
  * @ignore
@@ -108,6 +90,7 @@ function gatherPrimitiveStats(primitive) {
108
90
  };
109
91
 
110
92
  const vector = primitive.vector;
93
+ const polygon = primitive.polygon;
111
94
  const primitiveType = primitive.primitiveType;
112
95
  const positionAttribute = ModelUtility.getAttributeBySemantic(
113
96
  primitive,
@@ -120,29 +103,33 @@ function gatherPrimitiveStats(primitive) {
120
103
  : undefined;
121
104
 
122
105
  if (primitiveType === PrimitiveType.POINTS) {
123
- stats.pointPrimitiveCount += vector.count;
124
- stats.pointVertexCount += vector.count;
106
+ stats.pointPrimitiveCount += positionCount;
107
+ stats.pointVertexCount += positionCount;
125
108
  } else if (primitiveType === PrimitiveType.LINE_STRIP) {
126
- //>>includeStart('debug', pragmas.debug);
127
- assert(defined(indices), "Vector LINE_STRIP primitive must be indexed.");
128
- //>>includeEnd('debug');
129
-
130
- stats.polylinePrimitiveCount += vector.count;
131
- stats.polylineVertexCount += indices.length - (vector.count - 1);
132
- } else if (primitiveType === PrimitiveType.TRIANGLES) {
133
- //>>includeStart('debug', pragmas.debug);
134
- assert(defined(indices), "Vector TRIANGLES primitive must be indexed.");
135
- //>>includeEnd('debug');
136
-
137
- stats.polygonPrimitiveCount += vector.count;
138
- stats.polygonVertexCount += positionCount;
139
- stats.polygonTriangleCount += indices.length / 3;
140
-
141
- const polygonHoleCounts = vector.polygonHoleCounts;
142
- if (polygonHoleCounts) {
143
- for (let i = 0; i < polygonHoleCounts.length; i++) {
144
- stats.polygonHoleCount += polygonHoleCounts[i];
109
+ const stripCount = vector ? vector.count : getPrimitiveCount(indices);
110
+ stats.polylinePrimitiveCount += stripCount;
111
+ stats.polylineVertexCount += indices.length - stripCount + 1;
112
+ } else if (
113
+ primitiveType === PrimitiveType.TRIANGLES ||
114
+ primitiveType === PrimitiveType.LINE_LOOP
115
+ ) {
116
+ if (vector) {
117
+ stats.polygonPrimitiveCount += vector.count;
118
+ stats.polygonVertexCount += positionCount;
119
+ stats.polygonTriangleCount += indices.length / 3;
120
+
121
+ const polygonHoleCounts = vector.polygonHoleCounts;
122
+ if (polygonHoleCounts) {
123
+ for (let i = 0; i < polygonHoleCounts.length; i++) {
124
+ stats.polygonHoleCount += polygonHoleCounts[i];
125
+ }
145
126
  }
127
+ } else {
128
+ const loopCount = getPrimitiveCount(polygon.loopIndices);
129
+ stats.polygonPrimitiveCount += polygon.count;
130
+ stats.polygonVertexCount += polygon.loopIndices.length - loopCount + 1;
131
+ stats.polygonTriangleCount += polygon.triangleIndices.length;
132
+ stats.polygonHoleCount += loopCount - polygon.count;
146
133
  }
147
134
  } else {
148
135
  throw new RuntimeError(`Unexpected primitive type: ${primitiveType}`);
@@ -151,6 +138,27 @@ function gatherPrimitiveStats(primitive) {
151
138
  return stats;
152
139
  }
153
140
 
141
+ /**
142
+ * Returns the number of GL primitives, separated by primitive restart index
143
+ * values, defined in the given index list.
144
+ *
145
+ * @param {TypedArray} indices
146
+ * @ignore
147
+ */
148
+ function getPrimitiveCount(indices) {
149
+ const restart = getPrimitiveRestartIndex(indices);
150
+
151
+ let count = 0;
152
+
153
+ for (let i = 0; i < indices.length; i++) {
154
+ if (indices[i] === restart && i + 1 < indices.length) {
155
+ count++;
156
+ }
157
+ }
158
+
159
+ return count + 1;
160
+ }
161
+
154
162
  /**
155
163
  * @param {VectorGltf3DTileContent} content
156
164
  * @param {Primitive} primitive
@@ -166,7 +174,6 @@ function appendPrimitiveToBuffers(
166
174
  collectionIndex,
167
175
  features,
168
176
  ) {
169
- const vector = primitive.vector;
170
177
  const positionAttribute = ModelUtility.getAttributeBySemantic(
171
178
  primitive,
172
179
  VertexAttributeSemantic.POSITION,
@@ -174,134 +181,370 @@ function appendPrimitiveToBuffers(
174
181
  /** @type {TypedArray} */
175
182
  const collectionPositions =
176
183
  positionAttribute.typedArray ??
177
- ModelReader.readAttributeAsTypedArray(positionAttribute);
178
- const vertexCount = collectionPositions.length / 3;
184
+ (collection.positionNormalized
185
+ ? ModelReader.readAttributeAsRawCompactTypedArray(positionAttribute)
186
+ : ModelReader.readAttributeAsTypedArray(positionAttribute));
179
187
 
180
188
  /** @type {TypedArray} */
181
189
  const indices = primitive.indices
182
190
  ? ModelReader.readIndicesAsTypedArray(primitive.indices)
183
191
  : undefined;
184
192
 
185
- const featureIdComponent = primitive.featureIds?.[0];
193
+ const getFeature = createFeatureFactoryFn(content, primitive, features);
194
+
195
+ if (collection instanceof BufferPointCollection) {
196
+ appendBufferPoints(
197
+ collection,
198
+ collectionIndex,
199
+ collectionPositions,
200
+ indices,
201
+ getFeature,
202
+ );
203
+ } else if (collection instanceof BufferPolylineCollection) {
204
+ appendBufferPolylines(
205
+ collection,
206
+ collectionIndex,
207
+ collectionPositions,
208
+ indices,
209
+ getFeature,
210
+ );
211
+ } else if (collection instanceof BufferPolygonCollection) {
212
+ if (defined(primitive.vector)) {
213
+ appendBufferPolygonsDeprecated(
214
+ collection,
215
+ collectionIndex,
216
+ collectionPositions,
217
+ indices,
218
+ getFeature,
219
+ primitive.vector,
220
+ );
221
+ } else {
222
+ appendBufferPolygons(
223
+ collection,
224
+ collectionIndex,
225
+ collectionPositions,
226
+ getFeature,
227
+ primitive.polygon,
228
+ );
229
+ }
230
+ }
231
+ }
186
232
 
187
- /** @type {Attribute} */
188
- let featureIdAttribute;
233
+ /**
234
+ * @callback FeatureFactoryFn
235
+ * @param {number} vertexOffset
236
+ * @returns {Cesium3DTileVectorFeature|undefined}
237
+ * @ignore
238
+ */
239
+
240
+ /**
241
+ * Returns a factory function that, given a vertex offset, returns the
242
+ * Cesium3DTileVectorFeature instance associated with the vertex.
243
+ *
244
+ * @param {VectorGltf3DTileContent} content
245
+ * @param {Primitive} primitive
246
+ * @param {Map<number, Cesium3DTileVectorFeature>} features
247
+ * @returns {FeatureFactoryFn}
248
+ * @ignore
249
+ */
250
+ function createFeatureFactoryFn(content, primitive, features) {
251
+ // @ts-expect-error Missing types.
252
+ const label = content.tileset.featureIdLabel;
253
+ const featureIdComponent = ModelUtility.getFeatureIdsByLabel(
254
+ primitive.featureIds,
255
+ label,
256
+ );
257
+
258
+ if (!(featureIdComponent instanceof ModelComponents.FeatureIdAttribute)) {
259
+ return () => undefined;
260
+ }
261
+
262
+ const featureIdAttribute = ModelUtility.getAttributeBySemantic(
263
+ primitive,
264
+ VertexAttributeSemantic.FEATURE_ID,
265
+ featureIdComponent.setIndex,
266
+ );
189
267
 
190
268
  /** @type {TypedArray} */
191
- let featureIdArray;
269
+ const featureIdArray =
270
+ featureIdAttribute.typedArray ??
271
+ ModelReader.readAttributeAsTypedArray(featureIdAttribute);
272
+
273
+ for (let i = 0; i < featureIdArray.length; i++) {
274
+ const featureId = featureIdArray[i];
275
+ if (!features.has(featureId)) {
276
+ const feature = new Cesium3DTileVectorFeature(
277
+ content,
278
+ featureId,
279
+ featureIdComponent.propertyTableId,
280
+ );
281
+ features.set(featureId, feature);
282
+ }
283
+ }
192
284
 
193
- /**
194
- * @param {number} vertexOffset
195
- * @returns {Cesium3DTileVectorFeature}
196
- */
197
- function getFeature(vertexOffset) {
285
+ /** @type {FeatureFactoryFn} */
286
+ return function getFeature(vertexOffset) {
198
287
  const featureId = featureIdArray[vertexOffset];
199
288
  if (featureId !== featureIdComponent.nullFeatureId) {
200
289
  return features.get(featureId);
201
290
  }
202
- }
291
+ };
292
+ }
203
293
 
204
- if (featureIdComponent instanceof ModelComponents.FeatureIdAttribute) {
205
- featureIdAttribute = ModelUtility.getAttributeBySemantic(
206
- primitive,
207
- VertexAttributeSemantic.FEATURE_ID,
208
- featureIdComponent.setIndex,
294
+ /**
295
+ * @param {BufferPointCollection} collection
296
+ * @param {number} collectionIndex
297
+ * @param {TypedArray} collectionPositions
298
+ * @param {TypedArray} indices
299
+ * @param {FeatureFactoryFn} getFeature
300
+ * @ignore
301
+ */
302
+ function appendBufferPoints(
303
+ collection,
304
+ collectionIndex,
305
+ collectionPositions,
306
+ indices,
307
+ getFeature,
308
+ ) {
309
+ const vertexCount = collectionPositions.length / 3;
310
+
311
+ for (let i = 0, il = indices ? indices.length : vertexCount; i < il; i++) {
312
+ const vertexOffset = indices ? indices[i] : i;
313
+ Cartesian3.fromArray(
314
+ // @ts-expect-error https://github.com/CesiumGS/cesium/pull/13302
315
+ collectionPositions,
316
+ vertexOffset * 3,
317
+ scratchPosition,
209
318
  );
210
- featureIdArray =
211
- featureIdAttribute.typedArray ??
212
- ModelReader.readAttributeAsTypedArray(featureIdAttribute);
213
-
214
- for (let i = 0; i < featureIdArray.length; i++) {
215
- const featureId = featureIdArray[i];
216
- if (!features.has(featureId)) {
217
- const feature = new Cesium3DTileVectorFeature(
218
- content,
219
- featureId,
220
- featureIdComponent.propertyTableId,
221
- );
222
- features.set(featureId, feature);
223
- }
319
+
320
+ const feature = getFeature(vertexOffset);
321
+ if (feature) {
322
+ feature.addPrimitiveByCollection(collectionIndex, i);
224
323
  }
324
+
325
+ collection.add(
326
+ {
327
+ position: scratchPosition,
328
+ pickObject: feature,
329
+ featureId: feature?.featureId,
330
+ },
331
+ scratchPoint,
332
+ );
225
333
  }
334
+ }
226
335
 
227
- if (collection instanceof BufferPointCollection) {
228
- for (let i = 0, il = indices ? indices.length : vertexCount; i < il; i++) {
229
- const vertexOffset = indices ? indices[i] : i;
230
- Cartesian3.fromArray(
231
- // @ts-expect-error TODO(tsd-jsdoc): See https://github.com/CesiumGS/cesium/pull/13302.
232
- collectionPositions,
233
- vertexOffset * 3,
234
- scratchPosition,
235
- );
336
+ /**
337
+ * @param {BufferPolylineCollection} collection
338
+ * @param {number} collectionIndex
339
+ * @param {TypedArray} collectionPositions
340
+ * @param {TypedArray} indices
341
+ * @param {FeatureFactoryFn} getFeature
342
+ * @ignore
343
+ */
344
+ function appendBufferPolylines(
345
+ collection,
346
+ collectionIndex,
347
+ collectionPositions,
348
+ indices,
349
+ getFeature,
350
+ ) {
351
+ const restartIndex = getPrimitiveRestartIndex(indices);
352
+
353
+ let lineIndexStart = 0;
354
+ let lineIndexCount = 0;
355
+ let primitiveIndex = 0;
356
+
357
+ for (let i = 0; i < indices.length; i++) {
358
+ // Iteration has reached the end of a line strip primitive if the current
359
+ // index is a "restart index", or the next index is out of bounds.
360
+ const index = indices[i];
361
+ if (index === restartIndex) {
362
+ lineIndexCount = i - lineIndexStart;
363
+ } else if (i + 1 === indices.length) {
364
+ lineIndexCount = i + 1 - lineIndexStart;
365
+ }
236
366
 
237
- const pickObject = getFeature(vertexOffset);
238
- pickObject.addPrimitiveByCollection(collectionIndex, i);
239
- const featureId = pickObject.featureId;
367
+ if (lineIndexCount === 0) {
368
+ continue;
369
+ }
240
370
 
241
- collection.add(
242
- { position: scratchPosition, featureId, pickObject },
243
- scratchPoint,
244
- );
371
+ const lineIndexEnd = lineIndexStart + lineIndexCount;
372
+ const lineIndices = indices.subarray(lineIndexStart, lineIndexEnd);
373
+ const positions = copyArrayByIndices(collectionPositions, lineIndices, 3);
374
+
375
+ const feature = getFeature(indices[lineIndexStart]);
376
+ if (feature) {
377
+ feature.addPrimitiveByCollection(collectionIndex, primitiveIndex);
245
378
  }
246
- } else if (collection instanceof BufferPolylineCollection) {
247
- // @ts-expect-error TODO
248
- forEachLineStripSegment(indices, (indexOffset, indexCount) => {
249
- const i = collection.primitiveCount;
250
- const vertexOffset = indices[indexOffset];
251
- const positions = collectionPositions.subarray(
252
- vertexOffset * 3,
253
- (vertexOffset + indexCount) * 3,
254
- );
255
379
 
256
- const pickObject = getFeature(vertexOffset);
257
- pickObject.addPrimitiveByCollection(collectionIndex, i);
258
- const featureId = pickObject.featureId;
380
+ collection.add(
381
+ { positions, pickObject: feature, featureId: feature?.featureId },
382
+ scratchPolyline,
383
+ );
259
384
 
260
- collection.add({ positions, featureId, pickObject }, scratchPolyline);
261
- });
262
- } else if (collection instanceof BufferPolygonCollection) {
263
- const polygonAttributeOffsets = vector.polygonAttributeOffsets;
264
- const polygonIndicesOffsets = vector.polygonIndicesOffsets;
265
- const polygonHoleCounts = vector.polygonHoleCounts;
266
- const polygonHoleOffsets = vector.polygonHoleOffsets;
267
-
268
- const polygonCount = polygonAttributeOffsets.length;
269
- for (let i = 0; i < polygonCount; i++) {
270
- const polygonVertexStart = polygonAttributeOffsets[i];
271
- const polygonVertexEnd =
272
- i + 1 < polygonCount ? polygonAttributeOffsets[i + 1] : vertexCount;
273
-
274
- const positions = collectionPositions.subarray(
275
- polygonVertexStart * 3,
276
- polygonVertexEnd * 3,
277
- );
385
+ lineIndexStart = i + 1;
386
+ lineIndexCount = 0;
387
+ primitiveIndex++;
388
+ }
389
+ }
278
390
 
279
- let holes;
280
- if (defined(polygonHoleCounts) && polygonHoleCounts[i] > 0) {
281
- const holeCount = polygonHoleCounts[i];
282
- holes = polygonHoleOffsets.slice(i, i + holeCount);
283
- for (let h = 0; h < holeCount; h++) {
284
- holes[i] -= polygonVertexStart;
285
- }
286
- }
391
+ /**
392
+ * @param {BufferPolygonCollection} collection
393
+ * @param {number} collectionIndex
394
+ * @param {TypedArray} collectionPositions
395
+ * @param {TypedArray} indices
396
+ * @param {FeatureFactoryFn} getFeature
397
+ * @param {Vector} vector
398
+ * @deprecated To be removed after v1.142 release.
399
+ * @ignore
400
+ */
401
+ function appendBufferPolygonsDeprecated(
402
+ collection,
403
+ collectionIndex,
404
+ collectionPositions,
405
+ indices,
406
+ getFeature,
407
+ vector,
408
+ ) {
409
+ const polygonAttributeOffsets = vector.polygonAttributeOffsets;
410
+ const polygonIndicesOffsets = vector.polygonIndicesOffsets;
411
+ const polygonHoleCounts = vector.polygonHoleCounts;
412
+ const polygonHoleOffsets = vector.polygonHoleOffsets;
287
413
 
288
- const triangleIndexStart = polygonIndicesOffsets[i];
289
- const triangleIndexEnd =
290
- i + 1 < polygonCount ? polygonIndicesOffsets[i + 1] : indices.length;
291
- const triangles = indices.slice(triangleIndexStart, triangleIndexEnd);
292
- for (let t = 0; t < triangleIndexEnd; t++) {
293
- triangles[t] -= polygonVertexStart;
414
+ const vertexCount = collectionPositions.length / 3;
415
+ const polygonCount = polygonAttributeOffsets.length;
416
+ for (let i = 0; i < polygonCount; i++) {
417
+ const polygonVertexStart = polygonAttributeOffsets[i];
418
+ const polygonVertexEnd =
419
+ i + 1 < polygonCount ? polygonAttributeOffsets[i + 1] : vertexCount;
420
+
421
+ const positions = collectionPositions.subarray(
422
+ polygonVertexStart * 3,
423
+ polygonVertexEnd * 3,
424
+ );
425
+
426
+ let holes;
427
+ if (defined(polygonHoleCounts) && polygonHoleCounts[i] > 0) {
428
+ const holeCount = polygonHoleCounts[i];
429
+ holes = polygonHoleOffsets.slice(i, i + holeCount);
430
+ for (let h = 0; h < holeCount; h++) {
431
+ holes[h] -= polygonVertexStart;
294
432
  }
433
+ }
434
+
435
+ const triangleIndexStart = polygonIndicesOffsets[i];
436
+ const triangleIndexEnd =
437
+ i + 1 < polygonCount ? polygonIndicesOffsets[i + 1] : indices.length;
438
+ const triangles = indices.slice(triangleIndexStart, triangleIndexEnd);
439
+ for (let t = 0; t < triangles.length; t++) {
440
+ triangles[t] -= polygonVertexStart;
441
+ }
442
+
443
+ const feature = getFeature(polygonVertexStart);
444
+ if (feature) {
445
+ feature.addPrimitiveByCollection(collectionIndex, i);
446
+ }
295
447
 
296
- const pickObject = getFeature(polygonVertexStart);
297
- pickObject.addPrimitiveByCollection(collectionIndex, i);
298
- const featureId = pickObject.featureId;
448
+ collection.add(
449
+ {
450
+ positions,
451
+ triangles,
452
+ holes,
453
+ pickObject: feature,
454
+ featureId: feature?.featureId,
455
+ },
456
+ scratchPolygon,
457
+ );
458
+ }
459
+ }
299
460
 
300
- collection.add(
301
- { positions, triangles, holes, featureId, pickObject },
302
- scratchPolygon,
461
+ /**
462
+ * @param {BufferPolygonCollection} collection
463
+ * @param {number} collectionIndex
464
+ * @param {TypedArray} collectionPositions
465
+ * @param {FeatureFactoryFn} getFeature
466
+ * @param {Polygon} polygon
467
+ * @ignore
468
+ */
469
+ function appendBufferPolygons(
470
+ collection,
471
+ collectionIndex,
472
+ collectionPositions,
473
+ getFeature,
474
+ polygon,
475
+ ) {
476
+ // Create mapping from vertex index in the source glTF primitive, to result
477
+ // vertex index in the extracted vector primitive.
478
+ const TypedArray = /** @type {TypedArrayConstructor} */ (
479
+ polygon.loopIndices.constructor
480
+ );
481
+ const resultLoopIndices = new TypedArray(polygon.loopIndices.length);
482
+
483
+ const loopRestartIndex = getPrimitiveRestartIndex(polygon.loopIndices);
484
+
485
+ for (let i = 0; i < polygon.count; i++) {
486
+ const isLastPolygon = i + 1 === polygon.count;
487
+
488
+ // Extract vertex loops, exterior loops followed by interior ("holes").
489
+ const loopIndicesStart = polygon.loopIndicesOffsets[i];
490
+ const loopIndicesEnd = isLastPolygon
491
+ ? polygon.loopIndices.length
492
+ : polygon.loopIndicesOffsets[i + 1];
493
+ const loopIndices = polygon.loopIndices.subarray(
494
+ loopIndicesStart,
495
+ loopIndicesEnd,
496
+ );
497
+ const positions = copyArrayByIndices(
498
+ collectionPositions,
499
+ loopIndices,
500
+ 3,
501
+ resultLoopIndices,
502
+ );
503
+
504
+ // List start indices of interior loops ("holes").
505
+ const holesArray = [];
506
+ for (let j = 0; j < loopIndices.length; j++) {
507
+ const isLastIndex = j + 1 === loopIndices.length;
508
+ if (loopIndices[j] === loopRestartIndex && !isLastIndex) {
509
+ holesArray.push(j);
510
+ }
511
+ }
512
+ const holes = new TypedArray(holesArray);
513
+
514
+ // Extract or tessellate triangle indices.
515
+ let triangles;
516
+ if (defined(polygon.triangleIndices)) {
517
+ const triangleIndicesStart = polygon.triangleIndicesOffsets[i];
518
+ const triangleIndicesEnd = isLastPolygon
519
+ ? polygon.triangleIndices.length
520
+ : polygon.triangleIndicesOffsets[i + 1];
521
+ triangles = polygon.triangleIndices.subarray(
522
+ triangleIndicesStart,
523
+ triangleIndicesEnd,
303
524
  );
525
+ // Rewrite collection-local indices to polygon-local indices.
526
+ for (let j = 0; j < triangles.length; j++) {
527
+ triangles[j] = resultLoopIndices[triangles[j]];
528
+ }
529
+ } else {
530
+ throw new Error("Runtime triangulation not yet supported.");
531
+ }
532
+
533
+ const feature = getFeature(loopIndices[0]);
534
+ if (feature) {
535
+ feature.addPrimitiveByCollection(collectionIndex, i);
304
536
  }
537
+
538
+ collection.add(
539
+ {
540
+ positions,
541
+ triangles,
542
+ holes,
543
+ pickObject: feature,
544
+ featureId: feature?.featureId,
545
+ },
546
+ scratchPolygon,
547
+ );
305
548
  }
306
549
  }
307
550
 
@@ -324,45 +567,65 @@ function appendNodeToBuffers(content, node, parentTransform, result) {
324
567
  for (let i = 0; i < primitives.length; i++) {
325
568
  const primitive = primitives[i];
326
569
  const primitiveType = primitive.primitiveType;
327
- if (!primitive.vector) {
328
- continue;
329
- }
330
570
 
331
571
  /** @type {BufferPrimitiveCollection<BufferPrimitive>} */
332
572
  let collection;
333
573
 
334
574
  const stats = gatherPrimitiveStats(primitive);
335
575
 
576
+ const positionAttribute = ModelUtility.getAttributeBySemantic(
577
+ primitive,
578
+ VertexAttributeSemantic.POSITION,
579
+ );
580
+ const positionNormalized = positionAttribute.normalized ?? false;
581
+ const positionDatatype = positionAttribute.componentDatatype;
582
+
336
583
  if (primitiveType === PrimitiveType.POINTS) {
337
584
  collection = new BufferPointCollection({
338
585
  primitiveCountMax: stats.pointPrimitiveCount,
339
586
  allowPicking: true,
587
+ positionNormalized,
588
+ positionDatatype,
340
589
  });
341
590
  } else if (primitiveType === PrimitiveType.LINE_STRIP) {
342
591
  collection = new BufferPolylineCollection({
343
592
  primitiveCountMax: stats.polylinePrimitiveCount,
344
593
  vertexCountMax: stats.polylineVertexCount,
345
594
  allowPicking: true,
595
+ positionNormalized,
596
+ positionDatatype,
346
597
  });
347
- } else if (primitiveType === PrimitiveType.TRIANGLES) {
598
+ } else if (
599
+ primitiveType === PrimitiveType.TRIANGLES ||
600
+ primitiveType === PrimitiveType.LINE_LOOP
601
+ ) {
348
602
  collection = new BufferPolygonCollection({
349
603
  primitiveCountMax: stats.polygonPrimitiveCount,
350
604
  vertexCountMax: stats.polygonVertexCount,
351
605
  holeCountMax: stats.polygonHoleCount,
352
606
  triangleCountMax: stats.polygonTriangleCount,
353
607
  allowPicking: true,
608
+ positionNormalized,
609
+ positionDatatype,
354
610
  });
355
611
  }
356
612
 
613
+ const featureIdComponent = primitive.featureIds?.[0];
614
+ const propertyTableId = featureIdComponent?.propertyTableId;
615
+ if (!result.featuresByTableId.has(propertyTableId)) {
616
+ result.featuresByTableId.set(propertyTableId, new Map());
617
+ }
618
+
357
619
  result.collections.push(collection);
358
620
  result.collectionLocalMatrices.push(Matrix4.clone(nodeTransform));
621
+ result.collectionFeatureTableIds.set(collection, propertyTableId);
359
622
 
360
623
  appendPrimitiveToBuffers(
361
624
  content,
362
625
  primitive,
363
626
  collection,
364
627
  result.collections.length - 1,
365
- result.features,
628
+ result.featuresByTableId.get(propertyTableId),
366
629
  );
367
630
  }
368
631
 
@@ -372,4 +635,57 @@ function appendNodeToBuffers(content, node, parentTransform, result) {
372
635
  }
373
636
  }
374
637
 
638
+ /**
639
+ * Given a source array and a list of indices, creates and returns a new array
640
+ * containing all values of the source array specified by the indices. Indices
641
+ * may contain "primitive restart index" values. Optionally, a 'resultIndices'
642
+ * parameter can be populated with a mapping from source index to result index.
643
+ *
644
+ * @param {TypedArray} array
645
+ * @param {TypedArray} indices
646
+ * @param {number} stride
647
+ * @param {TypedArray} [resultIndices]
648
+ * @returns {TypedArray}
649
+ * @ignore
650
+ */
651
+ function copyArrayByIndices(array, indices, stride, resultIndices) {
652
+ const restartIndex = getPrimitiveRestartIndex(indices);
653
+
654
+ // Scan and count the number of non-restart indices.
655
+ let count = 0;
656
+ for (let i = 0; i < indices.length; i++) {
657
+ const index = indices[i];
658
+ if (index !== restartIndex) {
659
+ count++;
660
+ }
661
+ }
662
+
663
+ const TypedArray = /** @type {TypedArrayConstructor} */ (array.constructor);
664
+ const result = new TypedArray(count * stride);
665
+
666
+ // Write each result value, skipping primitive restart indices. Write source
667
+ // index -> result index to 'resultIndices' if provided.
668
+ let dstIndex = 0;
669
+ for (let i = 0; i < indices.length; i++) {
670
+ const srcIndex = indices[i];
671
+
672
+ if (resultIndices) {
673
+ resultIndices[srcIndex] =
674
+ srcIndex === restartIndex ? restartIndex : dstIndex;
675
+ }
676
+
677
+ if (srcIndex === restartIndex) {
678
+ continue;
679
+ }
680
+
681
+ for (let j = 0; j < stride; j++) {
682
+ result[dstIndex * stride + j] = array[srcIndex * stride + j];
683
+ }
684
+
685
+ dstIndex++;
686
+ }
687
+
688
+ return result;
689
+ }
690
+
375
691
  export default createVectorTileBuffersFromModelComponents;