@cesium/engine 0.1.0 → 1.1.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 (217) hide show
  1. package/Build/Workers/{AttributeCompression-4589338a.js → AttributeCompression-b646d393.js} +1 -1
  2. package/Build/Workers/{AxisAlignedBoundingBox-bfb1234f.js → AxisAlignedBoundingBox-a4321399.js} +1 -1
  3. package/Build/Workers/{BoundingRectangle-7ffc2153.js → BoundingRectangle-80d8801f.js} +1 -1
  4. package/Build/Workers/{BoxGeometry-93f344a3.js → BoxGeometry-33c10a4f.js} +1 -1
  5. package/Build/Workers/{Color-0c5aaf47.js → Color-1bf9a6e0.js} +1 -1
  6. package/Build/Workers/{CoplanarPolygonGeometryLibrary-6597982a.js → CoplanarPolygonGeometryLibrary-5c5b981b.js} +1 -1
  7. package/Build/Workers/{CorridorGeometryLibrary-2119580e.js → CorridorGeometryLibrary-7cbae7a0.js} +1 -1
  8. package/Build/Workers/{CylinderGeometry-f9503c6d.js → CylinderGeometry-42740df0.js} +1 -1
  9. package/Build/Workers/{EllipseGeometry-fedf72d5.js → EllipseGeometry-49a3ac21.js} +1 -1
  10. package/Build/Workers/{EllipseGeometryLibrary-4ea68687.js → EllipseGeometryLibrary-b891b2f8.js} +1 -1
  11. package/Build/Workers/{EllipseOutlineGeometry-e2ae6a35.js → EllipseOutlineGeometry-fbd72e07.js} +1 -1
  12. package/Build/Workers/{EllipsoidGeodesic-16de63ea.js → EllipsoidGeodesic-98c62a56.js} +1 -1
  13. package/Build/Workers/{EllipsoidGeometry-95c0330e.js → EllipsoidGeometry-a351dba8.js} +1 -1
  14. package/Build/Workers/{EllipsoidOutlineGeometry-d6d2ceec.js → EllipsoidOutlineGeometry-3e8779bf.js} +1 -1
  15. package/Build/Workers/{EllipsoidRhumbLine-ae5e65e0.js → EllipsoidRhumbLine-19756602.js} +1 -1
  16. package/Build/Workers/{EllipsoidTangentPlane-bfc674bf.js → EllipsoidTangentPlane-cfb50678.js} +1 -1
  17. package/Build/Workers/{EncodedCartesian3-f473ea18.js → EncodedCartesian3-81f70735.js} +1 -1
  18. package/Build/Workers/{FrustumGeometry-3bf2e4eb.js → FrustumGeometry-c5754412.js} +1 -1
  19. package/Build/Workers/{GeometryAttribute-df5f473e.js → GeometryAttribute-0bfd05e8.js} +1 -1
  20. package/Build/Workers/{GeometryInstance-aa75b4cf.js → GeometryInstance-451dc1cd.js} +1 -1
  21. package/Build/Workers/{GeometryPipeline-f0e46c42.js → GeometryPipeline-0166905d.js} +1 -1
  22. package/Build/Workers/{IntersectionTests-9de29d51.js → IntersectionTests-a93d3de9.js} +1 -1
  23. package/Build/Workers/{Matrix2-ce637455.js → Matrix2-13178034.js} +4 -2
  24. package/Build/Workers/{Matrix3-4f4df527.js → Matrix3-315394f6.js} +2 -1
  25. package/Build/Workers/{OrientedBoundingBox-d3ff3d4d.js → OrientedBoundingBox-b450cb61.js} +5 -5
  26. package/Build/Workers/{Plane-b81241c2.js → Plane-900aa728.js} +1 -1
  27. package/Build/Workers/{PolygonGeometryLibrary-6f4937bb.js → PolygonGeometryLibrary-f918ac26.js} +1 -1
  28. package/Build/Workers/PolygonPipeline-f59a8f0a.js +1345 -0
  29. package/Build/Workers/{PolylinePipeline-2e2b015c.js → PolylinePipeline-d8e6bd9b.js} +1 -1
  30. package/Build/Workers/{PolylineVolumeGeometryLibrary-7ee1d449.js → PolylineVolumeGeometryLibrary-125d2edf.js} +1 -1
  31. package/Build/Workers/{PrimitivePipeline-a9b7aae0.js → PrimitivePipeline-0d7b5ed4.js} +1 -1
  32. package/Build/Workers/{RectangleGeometryLibrary-9aa6c8f6.js → RectangleGeometryLibrary-0768db63.js} +1 -1
  33. package/Build/Workers/{TerrainEncoding-b52dcfc5.js → TerrainEncoding-06470d7f.js} +1 -1
  34. package/Build/Workers/{Transforms-2f755df8.js → Transforms-26539bce.js} +97 -83
  35. package/Build/Workers/{WallGeometryLibrary-ab19a93d.js → WallGeometryLibrary-6167b0fc.js} +1 -1
  36. package/Build/Workers/{WebMercatorProjection-9f25de49.js → WebMercatorProjection-13a90d41.js} +1 -1
  37. package/Build/Workers/cesiumWorkerBootstrapper.js +25 -1
  38. package/Build/Workers/combineGeometry.js +1 -1
  39. package/Build/Workers/createBoxGeometry.js +1 -1
  40. package/Build/Workers/createBoxOutlineGeometry.js +1 -1
  41. package/Build/Workers/createCircleGeometry.js +1 -1
  42. package/Build/Workers/createCircleOutlineGeometry.js +1 -1
  43. package/Build/Workers/createCoplanarPolygonGeometry.js +1 -1
  44. package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +1 -1
  45. package/Build/Workers/createCorridorGeometry.js +1 -1
  46. package/Build/Workers/createCorridorOutlineGeometry.js +1 -1
  47. package/Build/Workers/createCylinderGeometry.js +1 -1
  48. package/Build/Workers/createCylinderOutlineGeometry.js +1 -1
  49. package/Build/Workers/createEllipseGeometry.js +1 -1
  50. package/Build/Workers/createEllipseOutlineGeometry.js +1 -1
  51. package/Build/Workers/createEllipsoidGeometry.js +1 -1
  52. package/Build/Workers/createEllipsoidOutlineGeometry.js +1 -1
  53. package/Build/Workers/createFrustumGeometry.js +1 -1
  54. package/Build/Workers/createFrustumOutlineGeometry.js +1 -1
  55. package/Build/Workers/createGeometry.js +1 -1
  56. package/Build/Workers/createGroundPolylineGeometry.js +1 -1
  57. package/Build/Workers/createPlaneGeometry.js +1 -1
  58. package/Build/Workers/createPlaneOutlineGeometry.js +1 -1
  59. package/Build/Workers/createPolygonGeometry.js +1 -1
  60. package/Build/Workers/createPolygonOutlineGeometry.js +1 -1
  61. package/Build/Workers/createPolylineGeometry.js +1 -1
  62. package/Build/Workers/createPolylineVolumeGeometry.js +1 -1
  63. package/Build/Workers/createPolylineVolumeOutlineGeometry.js +1 -1
  64. package/Build/Workers/createRectangleGeometry.js +1 -1
  65. package/Build/Workers/createRectangleOutlineGeometry.js +1 -1
  66. package/Build/Workers/createSimplePolylineGeometry.js +1 -1
  67. package/Build/Workers/createSphereGeometry.js +1 -1
  68. package/Build/Workers/createSphereOutlineGeometry.js +1 -1
  69. package/Build/Workers/createVectorTileClampedPolylines.js +1 -1
  70. package/Build/Workers/createVectorTileGeometries.js +1 -1
  71. package/Build/Workers/createVectorTilePoints.js +1 -1
  72. package/Build/Workers/createVectorTilePolygons.js +1 -1
  73. package/Build/Workers/createVectorTilePolylines.js +1 -1
  74. package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +1 -1
  75. package/Build/Workers/createVerticesFromHeightmap.js +7 -3
  76. package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +1 -1
  77. package/Build/Workers/createWallGeometry.js +1 -1
  78. package/Build/Workers/createWallOutlineGeometry.js +1 -1
  79. package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +95 -76
  80. package/Build/Workers/decodeI3S.js +1 -1
  81. package/Build/Workers/package.js +25 -1
  82. package/Build/Workers/transferTypedArrayTest.js +25 -1
  83. package/Build/Workers/upsampleQuantizedTerrainMesh.js +1 -1
  84. package/README.md +9 -9
  85. package/Source/Core/EarthOrientationParameters.js +67 -63
  86. package/Source/Core/Ion.js +1 -1
  87. package/Source/Core/Matrix2.js +2 -1
  88. package/Source/Core/Matrix3.js +2 -1
  89. package/Source/Core/Matrix4.js +1 -0
  90. package/Source/Core/OrientedBoundingBox.js +4 -4
  91. package/Source/Core/S2Cell.js +3 -3
  92. package/Source/Core/Transforms.js +3 -7
  93. package/Source/DataSources/GpxDataSource.js +4 -6
  94. package/Source/DataSources/KmlDataSource.js +3 -5
  95. package/Source/Renderer/Context.js +230 -177
  96. package/Source/Renderer/Pass.js +3 -2
  97. package/Source/Scene/Cesium3DTileContentType.js +19 -0
  98. package/Source/Scene/Cesium3DTilesVoxelProvider.js +482 -0
  99. package/Source/Scene/Cesium3DTilesetMetadata.js +2 -2
  100. package/Source/Scene/ContentMetadata.js +2 -2
  101. package/Source/Scene/DerivedCommand.js +7 -0
  102. package/Source/Scene/Expression.js +1 -1
  103. package/Source/Scene/Globe.js +10 -0
  104. package/Source/Scene/GlobeSurfaceTileProvider.js +7 -0
  105. package/Source/Scene/GltfImageLoader.js +1 -1
  106. package/Source/Scene/GltfVertexBufferLoader.js +10 -2
  107. package/Source/Scene/GroupMetadata.js +2 -2
  108. package/Source/Scene/I3SDataProvider.js +2 -1
  109. package/Source/Scene/I3SFeature.js +1 -1
  110. package/Source/Scene/I3SLayer.js +64 -2
  111. package/Source/Scene/I3SNode.js +50 -6
  112. package/Source/Scene/ImplicitMetadataView.js +2 -2
  113. package/Source/Scene/ImplicitSubtreeCache.js +127 -0
  114. package/Source/Scene/ImplicitSubtreeMetadata.js +2 -2
  115. package/Source/Scene/ImplicitTileset.js +3 -2
  116. package/Source/Scene/KeyframeNode.js +47 -0
  117. package/Source/Scene/Megatexture.js +490 -0
  118. package/Source/Scene/MetadataClass.js +60 -25
  119. package/Source/Scene/MetadataClassProperty.js +132 -68
  120. package/Source/Scene/MetadataComponentType.js +78 -57
  121. package/Source/Scene/MetadataEnum.js +59 -23
  122. package/Source/Scene/MetadataEnumValue.js +49 -15
  123. package/Source/Scene/MetadataSchema.js +53 -24
  124. package/Source/Scene/MetadataSchemaLoader.js +2 -2
  125. package/Source/Scene/MetadataTableProperty.js +2 -2
  126. package/Source/Scene/MetadataType.js +6 -14
  127. package/Source/Scene/Model/GeoJsonLoader.js +1 -1
  128. package/Source/Scene/Model/Model.js +38 -6
  129. package/Source/Scene/Model/buildDrawCommand.js +19 -11
  130. package/Source/Scene/PointCloud.js +1 -1
  131. package/Source/Scene/PropertyAttribute.js +2 -2
  132. package/Source/Scene/PropertyAttributeProperty.js +2 -2
  133. package/Source/Scene/PropertyTable.js +2 -2
  134. package/Source/Scene/PropertyTexture.js +2 -2
  135. package/Source/Scene/PropertyTextureProperty.js +2 -2
  136. package/Source/Scene/ResourceCache.js +9 -1
  137. package/Source/Scene/ResourceCacheKey.js +9 -1
  138. package/Source/Scene/Scene.js +20 -50
  139. package/Source/Scene/SpatialNode.js +375 -0
  140. package/Source/Scene/StructuralMetadata.js +2 -2
  141. package/Source/Scene/TileMetadata.js +2 -2
  142. package/Source/Scene/TilesetMetadata.js +2 -2
  143. package/Source/Scene/VoxelBoxShape.js +527 -0
  144. package/Source/Scene/VoxelContent.js +169 -0
  145. package/Source/Scene/VoxelCylinderShape.js +937 -0
  146. package/Source/Scene/VoxelEllipsoidShape.js +937 -0
  147. package/Source/Scene/VoxelPrimitive.js +1919 -0
  148. package/Source/Scene/VoxelProvider.js +255 -0
  149. package/Source/Scene/VoxelRenderResources.js +224 -0
  150. package/Source/Scene/VoxelShape.js +152 -0
  151. package/Source/Scene/VoxelShapeType.js +105 -0
  152. package/Source/Scene/VoxelTraversal.js +1144 -0
  153. package/Source/Scene/buildVoxelDrawCommands.js +116 -0
  154. package/Source/Scene/parseBatchTable.js +18 -2
  155. package/Source/Scene/preprocess3DTileContent.js +8 -0
  156. package/Source/Scene/processVoxelProperties.js +455 -0
  157. package/Source/Shaders/BillboardCollectionVS.glsl +1 -1
  158. package/Source/Shaders/BillboardCollectionVS.js +1 -1
  159. package/Source/Shaders/Builtin/Constants/passOverlay.glsl +1 -1
  160. package/Source/Shaders/Builtin/Constants/passOverlay.js +1 -1
  161. package/Source/Shaders/Builtin/Constants/passVoxels.glsl +9 -0
  162. package/Source/Shaders/Builtin/Constants/passVoxels.js +11 -0
  163. package/Source/Shaders/Builtin/CzmBuiltins.js +2 -0
  164. package/Source/Shaders/Builtin/Functions/windowToEyeCoordinates.glsl +55 -43
  165. package/Source/Shaders/Builtin/Functions/windowToEyeCoordinates.js +55 -43
  166. package/Source/Shaders/GlobeFS.glsl +2 -1
  167. package/Source/Shaders/GlobeFS.js +2 -1
  168. package/Source/Shaders/PointPrimitiveCollectionVS.glsl +5 -2
  169. package/Source/Shaders/PointPrimitiveCollectionVS.js +5 -2
  170. package/Source/Shaders/Voxels/IntersectBox.glsl +79 -0
  171. package/Source/Shaders/Voxels/IntersectBox.js +81 -0
  172. package/Source/Shaders/Voxels/IntersectClippingPlanes.glsl +70 -0
  173. package/Source/Shaders/Voxels/IntersectClippingPlanes.js +72 -0
  174. package/Source/Shaders/Voxels/IntersectCylinder.glsl +273 -0
  175. package/Source/Shaders/Voxels/IntersectCylinder.js +275 -0
  176. package/Source/Shaders/Voxels/IntersectDepth.glsl +23 -0
  177. package/Source/Shaders/Voxels/IntersectDepth.js +25 -0
  178. package/Source/Shaders/Voxels/IntersectEllipsoid.glsl +337 -0
  179. package/Source/Shaders/Voxels/IntersectEllipsoid.js +339 -0
  180. package/Source/Shaders/Voxels/Intersection.glsl +54 -0
  181. package/Source/Shaders/Voxels/Intersection.js +56 -0
  182. package/Source/Shaders/Voxels/IntersectionUtils.glsl +151 -0
  183. package/Source/Shaders/Voxels/IntersectionUtils.js +153 -0
  184. package/Source/Shaders/Voxels/Megatexture.glsl +136 -0
  185. package/Source/Shaders/Voxels/Megatexture.js +138 -0
  186. package/Source/Shaders/Voxels/Octree.glsl +221 -0
  187. package/Source/Shaders/Voxels/Octree.js +223 -0
  188. package/Source/Shaders/Voxels/VoxelFS.glsl +150 -0
  189. package/Source/Shaders/Voxels/VoxelFS.js +152 -0
  190. package/Source/Shaders/Voxels/VoxelVS.glsl +11 -0
  191. package/Source/Shaders/Voxels/VoxelVS.js +13 -0
  192. package/Source/Shaders/Voxels/convertUvToBox.glsl +16 -0
  193. package/Source/Shaders/Voxels/convertUvToBox.js +18 -0
  194. package/Source/Shaders/Voxels/convertUvToCylinder.glsl +79 -0
  195. package/Source/Shaders/Voxels/convertUvToCylinder.js +81 -0
  196. package/Source/Shaders/Voxels/convertUvToEllipsoid.glsl +133 -0
  197. package/Source/Shaders/Voxels/convertUvToEllipsoid.js +135 -0
  198. package/Source/ThirdParty/Workers/draco_decoder_nodejs.js +100 -101
  199. package/Source/ThirdParty/Workers/pako_deflate.min.js +2 -2
  200. package/Source/ThirdParty/Workers/pako_inflate.min.js +2 -2
  201. package/Source/ThirdParty/draco_decoder.wasm +0 -0
  202. package/Source/Widget/CesiumWidget.js +1 -1
  203. package/index.d.ts +961 -56
  204. package/index.js +92 -60
  205. package/package.json +6 -4
  206. package/Build/ThirdParty/Workers/basis_transcoder.js +0 -2233
  207. package/Build/ThirdParty/Workers/draco_decoder_nodejs.js +0 -1872
  208. package/Build/ThirdParty/Workers/package.json +0 -1
  209. package/Build/ThirdParty/Workers/pako_deflate.min.js +0 -589
  210. package/Build/ThirdParty/Workers/pako_inflate.min.js +0 -798
  211. package/Build/ThirdParty/Workers/z-worker-pako.js +0 -503
  212. package/Build/ThirdParty/basis_transcoder.wasm +0 -0
  213. package/Build/ThirdParty/draco_decoder.wasm +0 -0
  214. package/Build/ThirdParty/google-earth-dbroot-parser.js +0 -8019
  215. package/Build/Widget/CesiumWidget.css +0 -120
  216. package/Build/Widget/lighter.css +0 -13
  217. package/Build/Workers/PolygonPipeline-774a8aaf.js +0 -1341
@@ -0,0 +1,1919 @@
1
+ import buildVoxelDrawCommands from "./buildVoxelDrawCommands.js";
2
+ import Cartesian2 from "../Core/Cartesian2.js";
3
+ import Cartesian3 from "../Core/Cartesian3.js";
4
+ import Cartesian4 from "../Core/Cartesian4.js";
5
+ import CesiumMath from "../Core/Math.js";
6
+ import Check from "../Core/Check.js";
7
+ import clone from "../Core/clone.js";
8
+ import Color from "../Core/Color.js";
9
+ import defaultValue from "../Core/defaultValue.js";
10
+ import defined from "../Core/defined.js";
11
+ import destroyObject from "../Core/destroyObject.js";
12
+ import DeveloperError from "../Core/DeveloperError.js";
13
+ import Event from "../Core/Event.js";
14
+ import JulianDate from "../Core/JulianDate.js";
15
+ import Matrix3 from "../Core/Matrix3.js";
16
+ import Matrix4 from "../Core/Matrix4.js";
17
+ import oneTimeWarning from "../Core/oneTimeWarning.js";
18
+ import ClippingPlaneCollection from "./ClippingPlaneCollection.js";
19
+ import Material from "./Material.js";
20
+ import MetadataComponentType from "./MetadataComponentType.js";
21
+ import MetadataType from "./MetadataType.js";
22
+ import PolylineCollection from "./PolylineCollection.js";
23
+ import VoxelShapeType from "./VoxelShapeType.js";
24
+ import VoxelTraversal from "./VoxelTraversal.js";
25
+ import CustomShader from "./Model/CustomShader.js";
26
+
27
+ /**
28
+ * A primitive that renders voxel data from a {@link VoxelProvider}.
29
+ *
30
+ * @alias VoxelPrimitive
31
+ * @constructor
32
+ *
33
+ * @param {Object} [options] Object with the following properties:
34
+ * @param {VoxelProvider} [options.provider] The voxel provider that supplies the primitive with tile data.
35
+ * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The model matrix used to transform the primitive.
36
+ * @param {CustomShader} [options.customShader] The custom shader used to style the primitive.
37
+ * @param {Clock} [options.clock] The clock used to control time dynamic behavior.
38
+ *
39
+ * @see VoxelProvider
40
+ * @see Cesium3DTilesVoxelProvider
41
+ * @see VoxelShapeType
42
+ *
43
+ * @experimental This feature is not final and is subject to change without Cesium's standard deprecation policy.
44
+ */
45
+ function VoxelPrimitive(options) {
46
+ options = defaultValue(options, defaultValue.EMPTY_OBJECT);
47
+
48
+ /**
49
+ * @type {Boolean}
50
+ * @private
51
+ */
52
+ this._ready = false;
53
+
54
+ /**
55
+ * @type {VoxelProvider}
56
+ * @private
57
+ */
58
+ this._provider = defaultValue(
59
+ options.provider,
60
+ VoxelPrimitive.DefaultProvider
61
+ );
62
+
63
+ /**
64
+ * This member is not created until the provider and shape are ready.
65
+ *
66
+ * @type {VoxelTraversal}
67
+ * @private
68
+ */
69
+ this._traversal = undefined;
70
+
71
+ /**
72
+ * This member is not created until the provider is ready.
73
+ *
74
+ * @type {VoxelShape}
75
+ * @private
76
+ */
77
+ this._shape = undefined;
78
+
79
+ /**
80
+ * @type {Boolean}
81
+ * @private
82
+ */
83
+ this._shapeVisible = false;
84
+
85
+ /**
86
+ * This member is not created until the provider is ready.
87
+ *
88
+ * @type {Cartesian3}
89
+ * @private
90
+ */
91
+ this._paddingBefore = new Cartesian3();
92
+
93
+ /**
94
+ * This member is not created until the provider is ready.
95
+ *
96
+ * @type {Cartesian3}
97
+ * @private
98
+ */
99
+ this._paddingAfter = new Cartesian3();
100
+
101
+ /**
102
+ * This member is not known until the provider is ready.
103
+ *
104
+ * @type {Cartesian3}
105
+ * @private
106
+ */
107
+ this._minBounds = new Cartesian3();
108
+
109
+ /**
110
+ * Used to detect if the shape is dirty.
111
+ * This member is not known until the provider is ready.
112
+ *
113
+ * @type {Cartesian3}
114
+ * @private
115
+ */
116
+ this._minBoundsOld = new Cartesian3();
117
+
118
+ /**
119
+ * This member is not known until the provider is ready.
120
+ *
121
+ * @type {Cartesian3}
122
+ * @private
123
+ */
124
+ this._maxBounds = new Cartesian3();
125
+
126
+ /**
127
+ * Used to detect if the shape is dirty.
128
+ * This member is not known until the provider is ready.
129
+ *
130
+ * @type {Cartesian3}
131
+ * @private
132
+ */
133
+ this._maxBoundsOld = new Cartesian3();
134
+
135
+ /**
136
+ * This member is not known until the provider is ready.
137
+ *
138
+ * @type {Cartesian3}
139
+ * @private
140
+ */
141
+ this._minClippingBounds = new Cartesian3();
142
+
143
+ /**
144
+ * Used to detect if the clipping is dirty.
145
+ * This member is not known until the provider is ready.
146
+ *
147
+ * @type {Cartesian3}
148
+ * @private
149
+ */
150
+ this._minClippingBoundsOld = new Cartesian3();
151
+
152
+ /**
153
+ * This member is not known until the provider is ready.
154
+ *
155
+ * @type {Cartesian3}
156
+ * @private
157
+ */
158
+ this._maxClippingBounds = new Cartesian3();
159
+
160
+ /**
161
+ * Used to detect if the clipping is dirty.
162
+ * This member is not known until the provider is ready.
163
+ *
164
+ * @type {Cartesian3}
165
+ * @private
166
+ */
167
+ this._maxClippingBoundsOld = new Cartesian3();
168
+
169
+ /**
170
+ * Clipping planes on the primitive
171
+ *
172
+ * @type {ClippingPlaneCollection}
173
+ * @private
174
+ */
175
+ this._clippingPlanes = undefined;
176
+
177
+ /**
178
+ * Keeps track of when the clipping planes change
179
+ *
180
+ * @type {Number}
181
+ * @private
182
+ */
183
+ this._clippingPlanesState = 0;
184
+
185
+ /**
186
+ * Keeps track of when the clipping planes are enabled / disabled
187
+ *
188
+ * @type {Boolean}
189
+ * @private
190
+ */
191
+ this._clippingPlanesEnabled = false;
192
+
193
+ /**
194
+ * The primitive's model matrix.
195
+ *
196
+ * @type {Matrix4}
197
+ * @private
198
+ */
199
+ this._modelMatrix = Matrix4.clone(
200
+ defaultValue(options.modelMatrix, Matrix4.IDENTITY)
201
+ );
202
+
203
+ /**
204
+ * The primitive's model matrix multiplied by the provider's model matrix.
205
+ * This member is not known until the provider is ready.
206
+ *
207
+ * @type {Matrix4}
208
+ * @private
209
+ */
210
+ this._compoundModelMatrix = new Matrix4();
211
+
212
+ /**
213
+ * Used to detect if the shape is dirty.
214
+ * This member is not known until the provider is ready.
215
+ *
216
+ * @type {Matrix4}
217
+ * @private
218
+ */
219
+ this._compoundModelMatrixOld = new Matrix4();
220
+
221
+ /**
222
+ * @type {CustomShader}
223
+ * @private
224
+ */
225
+ this._customShader = defaultValue(
226
+ options.customShader,
227
+ VoxelPrimitive.DefaultCustomShader
228
+ );
229
+
230
+ /**
231
+ * @type {Event}
232
+ * @private
233
+ */
234
+ this._customShaderCompilationEvent = new Event();
235
+
236
+ /**
237
+ * @type {Boolean}
238
+ * @private
239
+ */
240
+ this._shaderDirty = true;
241
+
242
+ /**
243
+ * @type {DrawCommand}
244
+ * @private
245
+ */
246
+ this._drawCommand = undefined;
247
+
248
+ /**
249
+ * @type {DrawCommand}
250
+ * @private
251
+ */
252
+ this._drawCommandPick = undefined;
253
+
254
+ /**
255
+ * @type {Object}
256
+ * @private
257
+ */
258
+ this._pickId = undefined;
259
+
260
+ /**
261
+ * @type {Clock}
262
+ * @private
263
+ */
264
+ this._clock = options.clock;
265
+
266
+ // Transforms and other values that are computed when the shape changes
267
+
268
+ /**
269
+ * @type {Matrix4}
270
+ * @private
271
+ */
272
+ this._transformPositionWorldToUv = new Matrix4();
273
+
274
+ /**
275
+ * @type {Matrix4}
276
+ * @private
277
+ */
278
+ this._transformPositionUvToWorld = new Matrix4();
279
+
280
+ /**
281
+ * @type {Matrix3}
282
+ * @private
283
+ */
284
+ this._transformDirectionWorldToLocal = new Matrix3();
285
+
286
+ /**
287
+ * @type {Matrix3}
288
+ * @private
289
+ */
290
+ this._transformNormalLocalToWorld = new Matrix3();
291
+
292
+ /**
293
+ * @type {Number}
294
+ * @private
295
+ */
296
+ this._stepSizeUv = 1.0;
297
+
298
+ // Rendering
299
+ /**
300
+ * @type {Boolean}
301
+ * @private
302
+ */
303
+ this._jitter = true;
304
+
305
+ /**
306
+ * @type {Boolean}
307
+ * @private
308
+ */
309
+ this._nearestSampling = false;
310
+
311
+ /**
312
+ * @type {Number}
313
+ * @private
314
+ */
315
+ this._levelBlendFactor = 0.0;
316
+
317
+ /**
318
+ * @type {Number}
319
+ * @private
320
+ */
321
+ this._stepSizeMultiplier = 1.0;
322
+
323
+ /**
324
+ * @type {Boolean}
325
+ * @private
326
+ */
327
+ this._depthTest = true;
328
+
329
+ /**
330
+ * @type {Boolean}
331
+ * @private
332
+ */
333
+ this._useLogDepth = undefined;
334
+
335
+ /**
336
+ * @type {Number}
337
+ * @private
338
+ */
339
+ this._screenSpaceError = 4.0; // in pixels
340
+
341
+ // Debug / statistics
342
+ /**
343
+ * @type {PolylineCollection}
344
+ * @private
345
+ */
346
+ this._debugPolylines = new PolylineCollection();
347
+
348
+ /**
349
+ * @type {Boolean}
350
+ * @private
351
+ */
352
+ this._debugDraw = false;
353
+
354
+ /**
355
+ * @type {Boolean}
356
+ * @private
357
+ */
358
+ this._disableRender = false;
359
+
360
+ /**
361
+ * @type {Boolean}
362
+ * @private
363
+ */
364
+ this._disableUpdate = false;
365
+
366
+ /**
367
+ * @type {Object.<string, any>}
368
+ * @private
369
+ */
370
+ this._uniforms = {
371
+ octreeInternalNodeTexture: undefined,
372
+ octreeInternalNodeTilesPerRow: 0,
373
+ octreeInternalNodeTexelSizeUv: new Cartesian2(),
374
+ octreeLeafNodeTexture: undefined,
375
+ octreeLeafNodeTilesPerRow: 0,
376
+ octreeLeafNodeTexelSizeUv: new Cartesian2(),
377
+ megatextureTextures: [],
378
+ megatextureSliceDimensions: new Cartesian2(),
379
+ megatextureTileDimensions: new Cartesian2(),
380
+ megatextureVoxelSizeUv: new Cartesian2(),
381
+ megatextureSliceSizeUv: new Cartesian2(),
382
+ megatextureTileSizeUv: new Cartesian2(),
383
+ dimensions: new Cartesian3(),
384
+ paddingBefore: new Cartesian3(),
385
+ paddingAfter: new Cartesian3(),
386
+ transformPositionViewToUv: new Matrix4(),
387
+ transformPositionUvToView: new Matrix4(),
388
+ transformDirectionViewToLocal: new Matrix3(),
389
+ transformNormalLocalToWorld: new Matrix3(),
390
+ cameraPositionUv: new Cartesian3(),
391
+ ndcSpaceAxisAlignedBoundingBox: new Cartesian4(),
392
+ clippingPlanesTexture: undefined,
393
+ clippingPlanesMatrix: new Matrix4(),
394
+ stepSize: 0,
395
+ pickColor: new Color(),
396
+ };
397
+
398
+ /**
399
+ * Shape specific shader defines from the previous shape update. Used to detect if the shader needs to be rebuilt.
400
+ * @type {Object.<string, any>}
401
+ * @private
402
+ */
403
+ this._shapeDefinesOld = {};
404
+
405
+ /**
406
+ * Map uniform names to functions that return the uniform values.
407
+ * @type {Object.<string, function():any>}
408
+ * @private
409
+ */
410
+ this._uniformMap = {};
411
+
412
+ const uniforms = this._uniforms;
413
+ const uniformMap = this._uniformMap;
414
+ for (const key in uniforms) {
415
+ if (uniforms.hasOwnProperty(key)) {
416
+ const name = `u_${key}`;
417
+ uniformMap[name] = function () {
418
+ return uniforms[key];
419
+ };
420
+ }
421
+ }
422
+
423
+ // If the provider fails to initialize the primitive will fail too.
424
+ const provider = this._provider;
425
+ this._completeLoad = function (primitive, frameState) {};
426
+ this._readyPromise = initialize(this, provider);
427
+ }
428
+
429
+ function initialize(primitive, provider) {
430
+ const promise = new Promise(function (resolve) {
431
+ primitive._completeLoad = function (primitive, frameState) {
432
+ // Set the primitive as ready after the first frame render since the user might set up events subscribed to
433
+ // the post render event, and the primitive may not be ready for those past the first frame.
434
+ frameState.afterRender.push(function () {
435
+ primitive._ready = true;
436
+ resolve(primitive);
437
+ return true;
438
+ });
439
+ };
440
+ });
441
+
442
+ return provider.readyPromise.then(function () {
443
+ return promise;
444
+ });
445
+ }
446
+
447
+ Object.defineProperties(VoxelPrimitive.prototype, {
448
+ /**
449
+ * Gets a value indicating whether or not the primitive is ready for use.
450
+ *
451
+ * @memberof VoxelPrimitive.prototype
452
+ * @type {Boolean}
453
+ * @readonly
454
+ */
455
+ ready: {
456
+ get: function () {
457
+ return this._ready;
458
+ },
459
+ },
460
+
461
+ /**
462
+ * Gets the promise that will be resolved when the primitive is ready for use.
463
+ *
464
+ * @memberof VoxelPrimitive.prototype
465
+ * @type {Promise.<VoxelPrimitive>}
466
+ * @readonly
467
+ */
468
+ readyPromise: {
469
+ get: function () {
470
+ return this._readyPromise;
471
+ },
472
+ },
473
+
474
+ /**
475
+ * Gets the {@link VoxelProvider} associated with this primitive.
476
+ *
477
+ * @memberof VoxelPrimitive.prototype
478
+ * @type {VoxelProvider}
479
+ * @readonly
480
+ */
481
+ provider: {
482
+ get: function () {
483
+ return this._provider;
484
+ },
485
+ },
486
+
487
+ /**
488
+ * Gets the bounding sphere.
489
+ *
490
+ * @memberof VoxelPrimitive.prototype
491
+ * @type {BoundingSphere}
492
+ * @readonly
493
+ *
494
+ * @exception {DeveloperError} If the primitive is not ready.
495
+ */
496
+ boundingSphere: {
497
+ get: function () {
498
+ //>>includeStart('debug', pragmas.debug);
499
+ if (!this._ready) {
500
+ throw new DeveloperError(
501
+ "boundingSphere must not be called before the primitive is ready."
502
+ );
503
+ }
504
+ //>>includeEnd('debug');
505
+
506
+ return this._shape.boundingSphere;
507
+ },
508
+ },
509
+
510
+ /**
511
+ * Gets the oriented bounding box.
512
+ *
513
+ * @memberof VoxelPrimitive.prototype
514
+ * @type {OrientedBoundingBox}
515
+ * @readonly
516
+ *
517
+ * @exception {DeveloperError} If the primitive is not ready.
518
+ */
519
+ orientedBoundingBox: {
520
+ get: function () {
521
+ //>>includeStart('debug', pragmas.debug);
522
+ if (!this._ready) {
523
+ throw new DeveloperError(
524
+ "orientedBoundingBox must not be called before the primitive is ready."
525
+ );
526
+ }
527
+ //>>includeEnd('debug');
528
+
529
+ return this._shape.orientedBoundingBox;
530
+ },
531
+ },
532
+
533
+ /**
534
+ * Gets the model matrix.
535
+ *
536
+ * @memberof VoxelPrimitive.prototype
537
+ * @type {Matrix4}
538
+ * @readonly
539
+ */
540
+ modelMatrix: {
541
+ get: function () {
542
+ return this._modelMatrix;
543
+ },
544
+ set: function (modelMatrix) {
545
+ //>>includeStart('debug', pragmas.debug);
546
+ Check.typeOf.object("modelMatrix", modelMatrix);
547
+ //>>includeEnd('debug');
548
+
549
+ this._modelMatrix = Matrix4.clone(modelMatrix, this._modelMatrix);
550
+ },
551
+ },
552
+
553
+ /**
554
+ * Gets the shape type.
555
+ *
556
+ * @memberof VoxelPrimitive.prototype
557
+ * @type {VoxelShapeType}
558
+ * @readonly
559
+ *
560
+ * @exception {DeveloperError} If the primitive is not ready.
561
+ */
562
+ shape: {
563
+ get: function () {
564
+ //>>includeStart('debug', pragmas.debug);
565
+ if (!this._ready) {
566
+ throw new DeveloperError(
567
+ "shape must not be called before the primitive is ready."
568
+ );
569
+ }
570
+ //>>includeEnd('debug');
571
+
572
+ return this._provider.shape;
573
+ },
574
+ },
575
+
576
+ /**
577
+ * Gets the voxel dimensions.
578
+ *
579
+ * @memberof VoxelPrimitive.prototype
580
+ * @type {Cartesian3}
581
+ * @readonly
582
+ *
583
+ * @exception {DeveloperError} If the primitive is not ready.
584
+ */
585
+ dimensions: {
586
+ get: function () {
587
+ //>>includeStart('debug', pragmas.debug);
588
+ if (!this._ready) {
589
+ throw new DeveloperError(
590
+ "dimensions must not be called before the primitive is ready."
591
+ );
592
+ }
593
+ //>>includeEnd('debug');
594
+
595
+ return this._provider.dimensions;
596
+ },
597
+ },
598
+
599
+ /**
600
+ * Gets the minimum value per channel of the voxel data.
601
+ *
602
+ * @memberof VoxelPrimitive.prototype
603
+ * @type {Number[][]}
604
+ * @readonly
605
+ *
606
+ * @exception {DeveloperError} If the primitive is not ready.
607
+ */
608
+ minimumValues: {
609
+ get: function () {
610
+ //>>includeStart('debug', pragmas.debug);
611
+ if (!this._ready) {
612
+ throw new DeveloperError(
613
+ "minimumValues must not be called before the primitive is ready."
614
+ );
615
+ }
616
+ //>>includeEnd('debug');
617
+
618
+ return this._provider.minimumValues;
619
+ },
620
+ },
621
+
622
+ /**
623
+ * Gets the maximum value per channel of the voxel data.
624
+ *
625
+ * @memberof VoxelPrimitive.prototype
626
+ * @type {Number[][]}
627
+ * @readonly
628
+ *
629
+ * @exception {DeveloperError} If the primitive is not ready.
630
+ */
631
+ maximumValues: {
632
+ get: function () {
633
+ //>>includeStart('debug', pragmas.debug);
634
+ if (!this._ready) {
635
+ throw new DeveloperError(
636
+ "maximumValues must not be called before the primitive is ready."
637
+ );
638
+ }
639
+ //>>includeEnd('debug');
640
+
641
+ return this._provider.maximumValues;
642
+ },
643
+ },
644
+
645
+ /**
646
+ * Gets or sets whether or not this primitive should be displayed.
647
+ *
648
+ * @memberof VoxelPrimitive.prototype
649
+ * @type {Boolean}
650
+ */
651
+ show: {
652
+ get: function () {
653
+ return !this._disableRender;
654
+ },
655
+ set: function (show) {
656
+ //>>includeStart('debug', pragmas.debug);
657
+ Check.typeOf.bool("show", show);
658
+ //>>includeEnd('debug');
659
+
660
+ this._disableRender = !show;
661
+ },
662
+ },
663
+
664
+ /**
665
+ * Gets or sets whether or not the primitive should update when the view changes.
666
+ *
667
+ * @memberof VoxelPrimitive.prototype
668
+ * @type {Boolean}
669
+ */
670
+ disableUpdate: {
671
+ get: function () {
672
+ return this._disableUpdate;
673
+ },
674
+ set: function (disableUpdate) {
675
+ //>>includeStart('debug', pragmas.debug);
676
+ Check.typeOf.bool("disableUpdate", disableUpdate);
677
+ //>>includeEnd('debug');
678
+
679
+ this._disableUpdate = disableUpdate;
680
+ },
681
+ },
682
+
683
+ /**
684
+ * Gets or sets whether or not to render debug visualizations.
685
+ *
686
+ * @memberof VoxelPrimitive.prototype
687
+ * @type {Boolean}
688
+ */
689
+ debugDraw: {
690
+ get: function () {
691
+ return this._debugDraw;
692
+ },
693
+ set: function (debugDraw) {
694
+ //>>includeStart('debug', pragmas.debug);
695
+ Check.typeOf.bool("debugDraw", debugDraw);
696
+ //>>includeEnd('debug');
697
+
698
+ this._debugDraw = debugDraw;
699
+ },
700
+ },
701
+
702
+ /**
703
+ * Gets or sets whether or not to test against depth when rendering.
704
+ *
705
+ * @memberof VoxelPrimitive.prototype
706
+ * @type {Boolean}
707
+ */
708
+ depthTest: {
709
+ get: function () {
710
+ return this._depthTest;
711
+ },
712
+ set: function (depthTest) {
713
+ //>>includeStart('debug', pragmas.debug);
714
+ Check.typeOf.bool("depthTest", depthTest);
715
+ //>>includeEnd('debug');
716
+
717
+ if (this._depthTest !== depthTest) {
718
+ this._depthTest = depthTest;
719
+ this._shaderDirty = true;
720
+ }
721
+ },
722
+ },
723
+
724
+ /**
725
+ * Gets or sets whether or not to jitter the view ray during the raymarch.
726
+ * This reduces stair-step artifacts but introduces noise.
727
+ *
728
+ * @memberof VoxelPrimitive.prototype
729
+ * @type {Boolean}
730
+ */
731
+ jitter: {
732
+ get: function () {
733
+ return this._jitter;
734
+ },
735
+ set: function (jitter) {
736
+ //>>includeStart('debug', pragmas.debug);
737
+ Check.typeOf.bool("jitter", jitter);
738
+ //>>includeEnd('debug');
739
+
740
+ if (this._jitter !== jitter) {
741
+ this._jitter = jitter;
742
+ this._shaderDirty = true;
743
+ }
744
+ },
745
+ },
746
+
747
+ /**
748
+ * Gets or sets the nearest sampling.
749
+ *
750
+ * @memberof VoxelPrimitive.prototype
751
+ * @type {Boolean}
752
+ */
753
+ nearestSampling: {
754
+ get: function () {
755
+ return this._nearestSampling;
756
+ },
757
+ set: function (nearestSampling) {
758
+ //>>includeStart('debug', pragmas.debug);
759
+ Check.typeOf.bool("nearestSampling", nearestSampling);
760
+ //>>includeEnd('debug');
761
+
762
+ if (this._nearestSampling !== nearestSampling) {
763
+ this._nearestSampling = nearestSampling;
764
+ this._shaderDirty = true;
765
+ }
766
+ },
767
+ },
768
+
769
+ /**
770
+ * Controls how quickly to blend between different levels of the tree.
771
+ * 0.0 means an instantaneous pop.
772
+ * 1.0 means a full linear blend.
773
+ *
774
+ * @memberof VoxelPrimitive.prototype
775
+ * @type {Number}
776
+ * @private
777
+ */
778
+ levelBlendFactor: {
779
+ get: function () {
780
+ return this._levelBlendFactor;
781
+ },
782
+ set: function (levelBlendFactor) {
783
+ //>>includeStart('debug', pragmas.debug);
784
+ Check.typeOf.number("levelBlendFactor", levelBlendFactor);
785
+ //>>includeEnd('debug');
786
+
787
+ this._levelBlendFactor = CesiumMath.clamp(levelBlendFactor, 0.0, 1.0);
788
+ },
789
+ },
790
+
791
+ /**
792
+ * Gets or sets the screen space error in pixels. If the screen space size
793
+ * of a voxel is greater than the screen space error, the tile is subdivided.
794
+ * Lower screen space error corresponds with higher detail rendering, but could
795
+ * result in worse performance and higher memory consumption.
796
+ *
797
+ * @memberof VoxelPrimitive.prototype
798
+ * @type {Number}
799
+ */
800
+ screenSpaceError: {
801
+ get: function () {
802
+ return this._screenSpaceError;
803
+ },
804
+ set: function (screenSpaceError) {
805
+ //>>includeStart('debug', pragmas.debug);
806
+ Check.typeOf.number("screenSpaceError", screenSpaceError);
807
+ //>>includeEnd('debug');
808
+
809
+ this._screenSpaceError = screenSpaceError;
810
+ },
811
+ },
812
+
813
+ /**
814
+ * Gets or sets the step size multiplier used during raymarching.
815
+ * The lower the value, the higher the rendering quality, but
816
+ * also the worse the performance.
817
+ *
818
+ * @memberof VoxelPrimitive.prototype
819
+ * @type {Number}
820
+ */
821
+ stepSize: {
822
+ get: function () {
823
+ return this._stepSizeMultiplier;
824
+ },
825
+ set: function (stepSize) {
826
+ //>>includeStart('debug', pragmas.debug);
827
+ Check.typeOf.number("stepSize", stepSize);
828
+ //>>includeEnd('debug');
829
+
830
+ this._stepSizeMultiplier = stepSize;
831
+ },
832
+ },
833
+
834
+ /**
835
+ * Gets or sets the minimum bounds in the shape's local coordinate system.
836
+ * Voxel data is stretched or squashed to fit the bounds.
837
+ *
838
+ * @memberof VoxelPrimitive.prototype
839
+ * @type {Cartesian3}
840
+ */
841
+ minBounds: {
842
+ get: function () {
843
+ return this._minBounds;
844
+ },
845
+ set: function (minBounds) {
846
+ //>>includeStart('debug', pragmas.debug);
847
+ Check.defined("minBounds", minBounds);
848
+ //>>includeEnd('debug');
849
+
850
+ this._minBounds = Cartesian3.clone(minBounds, this._minBounds);
851
+ },
852
+ },
853
+
854
+ /**
855
+ * Gets or sets the maximum bounds in the shape's local coordinate system.
856
+ * Voxel data is stretched or squashed to fit the bounds.
857
+ *
858
+ * @memberof VoxelPrimitive.prototype
859
+ * @type {Cartesian3}
860
+ */
861
+ maxBounds: {
862
+ get: function () {
863
+ return this._maxBounds;
864
+ },
865
+ set: function (maxBounds) {
866
+ //>>includeStart('debug', pragmas.debug);
867
+ Check.defined("maxBounds", maxBounds);
868
+ //>>includeEnd('debug');
869
+
870
+ this._maxBounds = Cartesian3.clone(maxBounds, this._maxBounds);
871
+ },
872
+ },
873
+
874
+ /**
875
+ * Gets or sets the minimum clipping location in the shape's local coordinate system.
876
+ * Any voxel content outside the range is clipped.
877
+ *
878
+ * @memberof VoxelPrimitive.prototype
879
+ * @type {Cartesian3}
880
+ */
881
+ minClippingBounds: {
882
+ get: function () {
883
+ return this._minClippingBounds;
884
+ },
885
+ set: function (minClippingBounds) {
886
+ //>>includeStart('debug', pragmas.debug);
887
+ Check.defined("minClippingBounds", minClippingBounds);
888
+ //>>includeEnd('debug');
889
+
890
+ this._minClippingBounds = Cartesian3.clone(
891
+ minClippingBounds,
892
+ this._minClippingBounds
893
+ );
894
+ },
895
+ },
896
+
897
+ /**
898
+ * Gets or sets the maximum clipping location in the shape's local coordinate system.
899
+ * Any voxel content outside the range is clipped.
900
+ *
901
+ * @memberof VoxelPrimitive.prototype
902
+ * @type {Cartesian3}
903
+ */
904
+ maxClippingBounds: {
905
+ get: function () {
906
+ return this._maxClippingBounds;
907
+ },
908
+ set: function (maxClippingBounds) {
909
+ //>>includeStart('debug', pragmas.debug);
910
+ Check.defined("maxClippingBounds", maxClippingBounds);
911
+ //>>includeEnd('debug');
912
+
913
+ this._maxClippingBounds = Cartesian3.clone(
914
+ maxClippingBounds,
915
+ this._maxClippingBounds
916
+ );
917
+ },
918
+ },
919
+
920
+ /**
921
+ * The {@link ClippingPlaneCollection} used to selectively disable rendering the primitive.
922
+ *
923
+ * @memberof VoxelPrimitive.prototype
924
+ * @type {ClippingPlaneCollection}
925
+ */
926
+ clippingPlanes: {
927
+ get: function () {
928
+ return this._clippingPlanes;
929
+ },
930
+ set: function (clippingPlanes) {
931
+ // Don't need to check if undefined, it's handled in the setOwner function
932
+ ClippingPlaneCollection.setOwner(clippingPlanes, this, "_clippingPlanes");
933
+ },
934
+ },
935
+
936
+ /**
937
+ * Gets or sets the custom shader. If undefined, {@link VoxelPrimitive.DefaultCustomShader} is set.
938
+ *
939
+ * @memberof VoxelPrimitive.prototype
940
+ * @type {CustomShader}
941
+ */
942
+ customShader: {
943
+ get: function () {
944
+ return this._customShader;
945
+ },
946
+ set: function (customShader) {
947
+ if (this._customShader !== customShader) {
948
+ // Delete old custom shader entries from the uniform map
949
+ const uniformMap = this._uniformMap;
950
+ const oldCustomShader = this._customShader;
951
+ const oldCustomShaderUniformMap = oldCustomShader.uniformMap;
952
+ for (const uniformName in oldCustomShaderUniformMap) {
953
+ if (oldCustomShaderUniformMap.hasOwnProperty(uniformName)) {
954
+ // If the custom shader was set but the voxel shader was never
955
+ // built, the custom shader uniforms wouldn't have been added to
956
+ // the uniform map. But it doesn't matter because the delete
957
+ // operator ignores if the key doesn't exist.
958
+ delete uniformMap[uniformName];
959
+ }
960
+ }
961
+
962
+ if (!defined(customShader)) {
963
+ this._customShader = VoxelPrimitive.DefaultCustomShader;
964
+ } else {
965
+ this._customShader = customShader;
966
+ }
967
+ this._shaderDirty = true;
968
+ }
969
+ },
970
+ },
971
+
972
+ /**
973
+ * Gets an event that is raised whenever a custom shader is compiled.
974
+ *
975
+ * @memberof VoxelPrimitive.prototype
976
+ * @type {Event}
977
+ * @readonly
978
+ */
979
+ customShaderCompilationEvent: {
980
+ get: function () {
981
+ return this._customShaderCompilationEvent;
982
+ },
983
+ },
984
+ });
985
+
986
+ const scratchDimensions = new Cartesian3();
987
+ const scratchIntersect = new Cartesian4();
988
+ const scratchNdcAabb = new Cartesian4();
989
+ const scratchScale = new Cartesian3();
990
+ const scratchLocalScale = new Cartesian3();
991
+ const scratchRotation = new Matrix3();
992
+ const scratchRotationAndLocalScale = new Matrix3();
993
+ const scratchTransformPositionWorldToLocal = new Matrix4();
994
+ const scratchTransformPositionLocalToWorld = new Matrix4();
995
+ const scratchTransformPositionLocalToProjection = new Matrix4();
996
+
997
+ const transformPositionLocalToUv = Matrix4.fromRotationTranslation(
998
+ Matrix3.fromUniformScale(0.5, new Matrix3()),
999
+ new Cartesian3(0.5, 0.5, 0.5),
1000
+ new Matrix4()
1001
+ );
1002
+ const transformPositionUvToLocal = Matrix4.fromRotationTranslation(
1003
+ Matrix3.fromUniformScale(2.0, new Matrix3()),
1004
+ new Cartesian3(-1.0, -1.0, -1.0),
1005
+ new Matrix4()
1006
+ );
1007
+
1008
+ /**
1009
+ * Updates the voxel primitive.
1010
+ *
1011
+ * @param {FrameState} frameState
1012
+ * @private
1013
+ */
1014
+ VoxelPrimitive.prototype.update = function (frameState) {
1015
+ const provider = this._provider;
1016
+
1017
+ // Update the custom shader in case it has texture uniforms.
1018
+ this._customShader.update(frameState);
1019
+
1020
+ // Exit early if it's not ready yet.
1021
+ if (!this._ready && !provider.ready) {
1022
+ return;
1023
+ }
1024
+
1025
+ // Initialize from the ready provider. This only happens once.
1026
+ const context = frameState.context;
1027
+ if (!this._ready) {
1028
+ initFromProvider(this, provider, context);
1029
+ this._completeLoad(this, frameState);
1030
+
1031
+ // Don't render until the next frame after the ready promise is resolved
1032
+ return;
1033
+ }
1034
+
1035
+ // Check if the shape is dirty before updating it. This needs to happen every
1036
+ // frame because the member variables can be modified externally via the
1037
+ // getters.
1038
+ const shapeDirty = checkTransformAndBounds(this, provider);
1039
+ const shape = this._shape;
1040
+ if (shapeDirty) {
1041
+ this._shapeVisible = updateShapeAndTransforms(this, shape, provider);
1042
+ if (checkShapeDefines(this, shape)) {
1043
+ this._shaderDirty = true;
1044
+ }
1045
+ }
1046
+ if (!this._shapeVisible) {
1047
+ return;
1048
+ }
1049
+
1050
+ // Update the traversal and prepare for rendering.
1051
+ const keyframeLocation = getKeyframeLocation(
1052
+ provider.timeIntervalCollection,
1053
+ this._clock
1054
+ );
1055
+
1056
+ const traversal = this._traversal;
1057
+ const sampleCountOld = traversal._sampleCount;
1058
+
1059
+ traversal.update(
1060
+ frameState,
1061
+ keyframeLocation,
1062
+ shapeDirty, // recomputeBoundingVolumes
1063
+ this._disableUpdate // pauseUpdate
1064
+ );
1065
+
1066
+ if (sampleCountOld !== traversal._sampleCount) {
1067
+ this._shaderDirty = true;
1068
+ }
1069
+
1070
+ if (!traversal.isRenderable(traversal.rootNode)) {
1071
+ return;
1072
+ }
1073
+
1074
+ if (this._debugDraw) {
1075
+ // Debug draw bounding boxes and other things. Must go after traversal update
1076
+ // because that's what updates the tile bounding boxes.
1077
+ debugDraw(this, frameState);
1078
+ }
1079
+
1080
+ if (this._disableRender) {
1081
+ return;
1082
+ }
1083
+
1084
+ // Check if log depth changed
1085
+ if (this._useLogDepth !== frameState.useLogDepth) {
1086
+ this._useLogDepth = frameState.useLogDepth;
1087
+ this._shaderDirty = true;
1088
+ }
1089
+
1090
+ // Check if clipping planes changed
1091
+ const clippingPlanesChanged = updateClippingPlanes(this, frameState);
1092
+ if (clippingPlanesChanged) {
1093
+ this._shaderDirty = true;
1094
+ }
1095
+
1096
+ const leafNodeTexture = traversal.leafNodeTexture;
1097
+ const uniforms = this._uniforms;
1098
+ if (defined(leafNodeTexture)) {
1099
+ uniforms.octreeLeafNodeTexture = traversal.leafNodeTexture;
1100
+ uniforms.octreeLeafNodeTexelSizeUv = Cartesian2.clone(
1101
+ traversal.leafNodeTexelSizeUv,
1102
+ uniforms.octreeLeafNodeTexelSizeUv
1103
+ );
1104
+ uniforms.octreeLeafNodeTilesPerRow = traversal.leafNodeTilesPerRow;
1105
+ }
1106
+
1107
+ // Rebuild shaders
1108
+ if (this._shaderDirty) {
1109
+ buildVoxelDrawCommands(this, context);
1110
+ this._shaderDirty = false;
1111
+ }
1112
+
1113
+ // Calculate the NDC-space AABB to "scissor" the fullscreen quad
1114
+ const transformPositionWorldToProjection =
1115
+ context.uniformState.viewProjection;
1116
+ const orientedBoundingBox = shape.orientedBoundingBox;
1117
+ const ndcAabb = orientedBoundingBoxToNdcAabb(
1118
+ orientedBoundingBox,
1119
+ transformPositionWorldToProjection,
1120
+ scratchNdcAabb
1121
+ );
1122
+
1123
+ // If the object is offscreen, don't render it.
1124
+ const offscreen =
1125
+ ndcAabb.x === +1.0 ||
1126
+ ndcAabb.y === +1.0 ||
1127
+ ndcAabb.z === -1.0 ||
1128
+ ndcAabb.w === -1.0;
1129
+ if (offscreen) {
1130
+ return;
1131
+ }
1132
+
1133
+ // Prepare to render: update uniforms that can change every frame
1134
+ // Using a uniform instead of going through RenderState's scissor because the viewport is not accessible here, and the scissor command needs pixel coordinates.
1135
+ uniforms.ndcSpaceAxisAlignedBoundingBox = Cartesian4.clone(
1136
+ ndcAabb,
1137
+ uniforms.ndcSpaceAxisAlignedBoundingBox
1138
+ );
1139
+ const transformPositionViewToWorld = context.uniformState.inverseView;
1140
+ uniforms.transformPositionViewToUv = Matrix4.multiply(
1141
+ this._transformPositionWorldToUv,
1142
+ transformPositionViewToWorld,
1143
+ uniforms.transformPositionViewToUv
1144
+ );
1145
+ const transformPositionWorldToView = context.uniformState.view;
1146
+ uniforms.transformPositionUvToView = Matrix4.multiply(
1147
+ transformPositionWorldToView,
1148
+ this._transformPositionUvToWorld,
1149
+ uniforms.transformPositionUvToView
1150
+ );
1151
+ const transformDirectionViewToWorld =
1152
+ context.uniformState.inverseViewRotation;
1153
+ uniforms.transformDirectionViewToLocal = Matrix3.multiply(
1154
+ this._transformDirectionWorldToLocal,
1155
+ transformDirectionViewToWorld,
1156
+ uniforms.transformDirectionViewToLocal
1157
+ );
1158
+ uniforms.transformNormalLocalToWorld = Matrix3.clone(
1159
+ this._transformNormalLocalToWorld,
1160
+ uniforms.transformNormalLocalToWorld
1161
+ );
1162
+ const cameraPositionWorld = frameState.camera.positionWC;
1163
+ uniforms.cameraPositionUv = Matrix4.multiplyByPoint(
1164
+ this._transformPositionWorldToUv,
1165
+ cameraPositionWorld,
1166
+ uniforms.cameraPositionUv
1167
+ );
1168
+ uniforms.stepSize = this._stepSizeUv * this._stepSizeMultiplier;
1169
+
1170
+ // Render the primitive
1171
+ const command = frameState.passes.pick
1172
+ ? this._drawCommandPick
1173
+ : this._drawCommand;
1174
+ command.boundingVolume = shape.boundingSphere;
1175
+ frameState.commandList.push(command);
1176
+ };
1177
+
1178
+ /**
1179
+ * Initialize primitive properties that are derived from the voxel provider
1180
+ * @param {VoxelPrimitive} primitive
1181
+ * @param {VoxelProvider} provider
1182
+ * @param {Context} context
1183
+ * @private
1184
+ */
1185
+ function initFromProvider(primitive, provider, context) {
1186
+ const uniforms = primitive._uniforms;
1187
+
1188
+ primitive._pickId = context.createPickId({ primitive });
1189
+ uniforms.pickColor = Color.clone(primitive._pickId.color, uniforms.pickColor);
1190
+
1191
+ // Set the bounds
1192
+ const {
1193
+ shape: shapeType,
1194
+ minBounds = VoxelShapeType.getMinBounds(shapeType),
1195
+ maxBounds = VoxelShapeType.getMaxBounds(shapeType),
1196
+ } = provider;
1197
+
1198
+ primitive.minBounds = minBounds;
1199
+ primitive.maxBounds = maxBounds;
1200
+ primitive.minClippingBounds = VoxelShapeType.getMinBounds(shapeType);
1201
+ primitive.maxClippingBounds = VoxelShapeType.getMaxBounds(shapeType);
1202
+
1203
+ checkTransformAndBounds(primitive, provider);
1204
+
1205
+ // Create the shape object, and update it so it is valid for VoxelTraversal
1206
+ const ShapeConstructor = VoxelShapeType.getShapeConstructor(shapeType);
1207
+ primitive._shape = new ShapeConstructor();
1208
+ primitive._shapeVisible = updateShapeAndTransforms(
1209
+ primitive,
1210
+ primitive._shape,
1211
+ provider
1212
+ );
1213
+
1214
+ const { shaderDefines, shaderUniforms: shapeUniforms } = primitive._shape;
1215
+ primitive._shapeDefinesOld = clone(shaderDefines, true);
1216
+
1217
+ // Add shape uniforms to the uniform map
1218
+ const uniformMap = primitive._uniformMap;
1219
+ for (const key in shapeUniforms) {
1220
+ if (shapeUniforms.hasOwnProperty(key)) {
1221
+ const name = `u_${key}`;
1222
+
1223
+ //>>includeStart('debug', pragmas.debug);
1224
+ if (defined(uniformMap[name])) {
1225
+ oneTimeWarning(
1226
+ `VoxelPrimitive: Uniform name "${name}" is already defined`
1227
+ );
1228
+ }
1229
+ //>>includeEnd('debug');
1230
+
1231
+ uniformMap[name] = function () {
1232
+ return shapeUniforms[key];
1233
+ };
1234
+ }
1235
+ }
1236
+
1237
+ // Set uniforms that come from the provider.
1238
+ // Note that minBounds and maxBounds can be set dynamically, so their uniforms aren't set here.
1239
+ uniforms.dimensions = Cartesian3.clone(
1240
+ provider.dimensions,
1241
+ uniforms.dimensions
1242
+ );
1243
+ primitive._paddingBefore = Cartesian3.clone(
1244
+ defaultValue(provider.paddingBefore, Cartesian3.ZERO),
1245
+ primitive._paddingBefore
1246
+ );
1247
+ uniforms.paddingBefore = Cartesian3.clone(
1248
+ primitive._paddingBefore,
1249
+ uniforms.paddingBefore
1250
+ );
1251
+ primitive._paddingAfter = Cartesian3.clone(
1252
+ defaultValue(provider.paddingAfter, Cartesian3.ZERO),
1253
+ primitive._paddingBefore
1254
+ );
1255
+ uniforms.paddingAfter = Cartesian3.clone(
1256
+ primitive._paddingAfter,
1257
+ uniforms.paddingAfter
1258
+ );
1259
+
1260
+ // Create the VoxelTraversal, and set related uniforms
1261
+ primitive._traversal = setupTraversal(primitive, provider, context);
1262
+ setTraversalUniforms(primitive._traversal, uniforms);
1263
+ }
1264
+
1265
+ /**
1266
+ * Track changes in provider transform and primitive bounds
1267
+ * @param {VoxelPrimitive} primitive
1268
+ * @param {VoxelProvider} provider
1269
+ * @returns {Boolean} Whether any of the transform or bounds changed
1270
+ * @private
1271
+ */
1272
+ function checkTransformAndBounds(primitive, provider) {
1273
+ const shapeTransform = defaultValue(
1274
+ provider.shapeTransform,
1275
+ Matrix4.IDENTITY
1276
+ );
1277
+ const globalTransform = defaultValue(
1278
+ provider.globalTransform,
1279
+ Matrix4.IDENTITY
1280
+ );
1281
+
1282
+ // Compound model matrix = global transform * model matrix * shape transform
1283
+ Matrix4.multiplyTransformation(
1284
+ globalTransform,
1285
+ primitive._modelMatrix,
1286
+ primitive._compoundModelMatrix
1287
+ );
1288
+ Matrix4.multiplyTransformation(
1289
+ primitive._compoundModelMatrix,
1290
+ shapeTransform,
1291
+ primitive._compoundModelMatrix
1292
+ );
1293
+ const numChanges =
1294
+ updateBound(primitive, "_compoundModelMatrix", "_compoundModelMatrixOld") +
1295
+ updateBound(primitive, "_minBounds", "_minBoundsOld") +
1296
+ updateBound(primitive, "_maxBounds", "_maxBoundsOld") +
1297
+ updateBound(primitive, "_minClippingBounds", "_minClippingBoundsOld") +
1298
+ updateBound(primitive, "_maxClippingBounds", "_maxClippingBoundsOld");
1299
+ return numChanges > 0;
1300
+ }
1301
+
1302
+ /**
1303
+ * Compare old and new values of a bound and update the old if it is different.
1304
+ * @param {VoxelPrimitive} primitive The primitive with bounds properties
1305
+ * @param {String} newBoundKey A key pointing to a bounds property of type Cartesian3 or Matrix4
1306
+ * @param {String} oldBoundKey A key pointing to a bounds property of the same type as the property at newBoundKey
1307
+ * @returns {Number} 1 if the bound value changed, 0 otherwise
1308
+ *
1309
+ * @private
1310
+ */
1311
+ function updateBound(primitive, newBoundKey, oldBoundKey) {
1312
+ const newBound = primitive[newBoundKey];
1313
+ const oldBound = primitive[oldBoundKey];
1314
+
1315
+ const changed = !newBound.equals(oldBound);
1316
+ if (changed) {
1317
+ newBound.clone(oldBound);
1318
+ }
1319
+ return changed ? 1 : 0;
1320
+ }
1321
+
1322
+ /**
1323
+ * Update the shape and related transforms
1324
+ * @param {VoxelPrimitive} primitive
1325
+ * @param {VoxelShape} shape
1326
+ * @param {VoxelProvider} provider
1327
+ * @returns {Boolean} True if the shape is visible
1328
+ * @private
1329
+ */
1330
+ function updateShapeAndTransforms(primitive, shape, provider) {
1331
+ const visible = shape.update(
1332
+ primitive._compoundModelMatrix,
1333
+ primitive.minBounds,
1334
+ primitive.maxBounds,
1335
+ primitive.minClippingBounds,
1336
+ primitive.maxClippingBounds
1337
+ );
1338
+ if (!visible) {
1339
+ return false;
1340
+ }
1341
+
1342
+ const transformPositionLocalToWorld = shape.shapeTransform;
1343
+ const transformPositionWorldToLocal = Matrix4.inverse(
1344
+ transformPositionLocalToWorld,
1345
+ scratchTransformPositionWorldToLocal
1346
+ );
1347
+ const rotation = Matrix4.getRotation(
1348
+ transformPositionLocalToWorld,
1349
+ scratchRotation
1350
+ );
1351
+ // Note that inverse(rotation) is the same as transpose(rotation)
1352
+ const scale = Matrix4.getScale(transformPositionLocalToWorld, scratchScale);
1353
+ const maximumScaleComponent = Cartesian3.maximumComponent(scale);
1354
+ const localScale = Cartesian3.divideByScalar(
1355
+ scale,
1356
+ maximumScaleComponent,
1357
+ scratchLocalScale
1358
+ );
1359
+ const rotationAndLocalScale = Matrix3.multiplyByScale(
1360
+ rotation,
1361
+ localScale,
1362
+ scratchRotationAndLocalScale
1363
+ );
1364
+
1365
+ // Set member variables when the shape is dirty
1366
+ const dimensions = provider.dimensions;
1367
+ primitive._stepSizeUv = shape.computeApproximateStepSize(dimensions);
1368
+ primitive._transformPositionWorldToUv = Matrix4.multiply(
1369
+ transformPositionLocalToUv,
1370
+ transformPositionWorldToLocal,
1371
+ primitive._transformPositionWorldToUv
1372
+ );
1373
+ primitive._transformPositionUvToWorld = Matrix4.multiply(
1374
+ transformPositionLocalToWorld,
1375
+ transformPositionUvToLocal,
1376
+ primitive._transformPositionUvToWorld
1377
+ );
1378
+ primitive._transformDirectionWorldToLocal = Matrix4.getMatrix3(
1379
+ transformPositionWorldToLocal,
1380
+ primitive._transformDirectionWorldToLocal
1381
+ );
1382
+ primitive._transformNormalLocalToWorld = Matrix3.inverseTranspose(
1383
+ rotationAndLocalScale,
1384
+ primitive._transformNormalLocalToWorld
1385
+ );
1386
+
1387
+ return true;
1388
+ }
1389
+
1390
+ /**
1391
+ * Set up a VoxelTraversal based on dimensions and types from the primitive and provider
1392
+ * @param {VoxelPrimitive} primitive
1393
+ * @param {VoxelProvider} provider
1394
+ * @param {Context} context
1395
+ * @returns {VoxelTraversal}
1396
+ * @private
1397
+ */
1398
+ function setupTraversal(primitive, provider, context) {
1399
+ const dimensions = Cartesian3.clone(provider.dimensions, scratchDimensions);
1400
+ Cartesian3.add(dimensions, primitive._paddingBefore, dimensions);
1401
+ Cartesian3.add(dimensions, primitive._paddingAfter, dimensions);
1402
+
1403
+ // It's ok for memory byte length to be undefined.
1404
+ // The system will choose a default memory size.
1405
+ const maximumTileCount = provider.maximumTileCount;
1406
+ const maximumTextureMemoryByteLength = defined(maximumTileCount)
1407
+ ? VoxelTraversal.getApproximateTextureMemoryByteLength(
1408
+ maximumTileCount,
1409
+ dimensions,
1410
+ provider.types,
1411
+ provider.componentTypes
1412
+ )
1413
+ : undefined;
1414
+
1415
+ const keyframeCount = defaultValue(provider.keyframeCount, 1);
1416
+
1417
+ return new VoxelTraversal(
1418
+ primitive,
1419
+ context,
1420
+ dimensions,
1421
+ provider.types,
1422
+ provider.componentTypes,
1423
+ keyframeCount,
1424
+ maximumTextureMemoryByteLength
1425
+ );
1426
+ }
1427
+
1428
+ /**
1429
+ * Set uniforms that come from the traversal.
1430
+ * @param {VoxelTraversal} traversal
1431
+ * @param {Object} uniforms
1432
+ * @private
1433
+ */
1434
+ function setTraversalUniforms(traversal, uniforms) {
1435
+ uniforms.octreeInternalNodeTexture = traversal.internalNodeTexture;
1436
+ uniforms.octreeInternalNodeTexelSizeUv = Cartesian2.clone(
1437
+ traversal.internalNodeTexelSizeUv,
1438
+ uniforms.octreeInternalNodeTexelSizeUv
1439
+ );
1440
+ uniforms.octreeInternalNodeTilesPerRow = traversal.internalNodeTilesPerRow;
1441
+
1442
+ const megatextures = traversal.megatextures;
1443
+ const megatexture = megatextures[0];
1444
+ const megatextureLength = megatextures.length;
1445
+ uniforms.megatextureTextures = new Array(megatextureLength);
1446
+ for (let i = 0; i < megatextureLength; i++) {
1447
+ uniforms.megatextureTextures[i] = megatextures[i].texture;
1448
+ }
1449
+
1450
+ uniforms.megatextureSliceDimensions = Cartesian2.clone(
1451
+ megatexture.sliceCountPerRegion,
1452
+ uniforms.megatextureSliceDimensions
1453
+ );
1454
+ uniforms.megatextureTileDimensions = Cartesian2.clone(
1455
+ megatexture.regionCountPerMegatexture,
1456
+ uniforms.megatextureTileDimensions
1457
+ );
1458
+ uniforms.megatextureVoxelSizeUv = Cartesian2.clone(
1459
+ megatexture.voxelSizeUv,
1460
+ uniforms.megatextureVoxelSizeUv
1461
+ );
1462
+ uniforms.megatextureSliceSizeUv = Cartesian2.clone(
1463
+ megatexture.sliceSizeUv,
1464
+ uniforms.megatextureSliceSizeUv
1465
+ );
1466
+ uniforms.megatextureTileSizeUv = Cartesian2.clone(
1467
+ megatexture.regionSizeUv,
1468
+ uniforms.megatextureTileSizeUv
1469
+ );
1470
+ }
1471
+
1472
+ /**
1473
+ * Track changes in shape-related shader defines
1474
+ * @param {VoxelPrimitive} primitive
1475
+ * @param {VoxelShape} shape
1476
+ * @returns {Boolean} True if any of the shape defines changed, requiring a shader rebuild
1477
+ * @private
1478
+ */
1479
+ function checkShapeDefines(primitive, shape) {
1480
+ const shapeDefines = shape.shaderDefines;
1481
+ const shapeDefinesChanged = Object.keys(shapeDefines).some(
1482
+ (key) => shapeDefines[key] !== primitive._shapeDefinesOld[key]
1483
+ );
1484
+ if (shapeDefinesChanged) {
1485
+ primitive._shapeDefinesOld = clone(shapeDefines, true);
1486
+ }
1487
+ return shapeDefinesChanged;
1488
+ }
1489
+
1490
+ /**
1491
+ * Find the keyframe location to render at. Doesn't need to be a whole number.
1492
+ * @param {TimeIntervalCollection} timeIntervalCollection
1493
+ * @param {Clock} clock
1494
+ * @returns {Number}
1495
+ *
1496
+ * @private
1497
+ */
1498
+ function getKeyframeLocation(timeIntervalCollection, clock) {
1499
+ if (!defined(timeIntervalCollection) || !defined(clock)) {
1500
+ return 0.0;
1501
+ }
1502
+ let date = clock.currentTime;
1503
+ let timeInterval;
1504
+ let timeIntervalIndex = timeIntervalCollection.indexOf(date);
1505
+ if (timeIntervalIndex >= 0) {
1506
+ timeInterval = timeIntervalCollection.get(timeIntervalIndex);
1507
+ } else {
1508
+ // Date fell outside the range
1509
+ timeIntervalIndex = ~timeIntervalIndex;
1510
+ if (timeIntervalIndex === timeIntervalCollection.length) {
1511
+ // Date past range
1512
+ timeIntervalIndex = timeIntervalCollection.length - 1;
1513
+ timeInterval = timeIntervalCollection.get(timeIntervalIndex);
1514
+ date = timeInterval.stop;
1515
+ } else {
1516
+ // Date before range
1517
+ timeInterval = timeIntervalCollection.get(timeIntervalIndex);
1518
+ date = timeInterval.start;
1519
+ }
1520
+ }
1521
+ // De-lerp between the start and end of the interval
1522
+ const totalSeconds = JulianDate.secondsDifference(
1523
+ timeInterval.stop,
1524
+ timeInterval.start
1525
+ );
1526
+ const secondsDifferenceStart = JulianDate.secondsDifference(
1527
+ date,
1528
+ timeInterval.start
1529
+ );
1530
+ const t = secondsDifferenceStart / totalSeconds;
1531
+
1532
+ return timeIntervalIndex + t;
1533
+ }
1534
+
1535
+ /**
1536
+ * Update the clipping planes state and associated uniforms
1537
+ *
1538
+ * @param {VoxelPrimitive} primitive
1539
+ * @param {FrameState} frameState
1540
+ * @returns {Boolean} Whether the clipping planes changed, requiring a shader rebuild
1541
+ * @private
1542
+ */
1543
+ function updateClippingPlanes(primitive, frameState) {
1544
+ const clippingPlanes = primitive.clippingPlanes;
1545
+ if (!defined(clippingPlanes)) {
1546
+ return false;
1547
+ }
1548
+
1549
+ clippingPlanes.update(frameState);
1550
+
1551
+ const { clippingPlanesState, enabled } = clippingPlanes;
1552
+
1553
+ if (enabled) {
1554
+ const uniforms = primitive._uniforms;
1555
+ uniforms.clippingPlanesTexture = clippingPlanes.texture;
1556
+
1557
+ // Compute the clipping plane's transformation to uv space and then take the inverse
1558
+ // transpose to properly transform the hessian normal form of the plane.
1559
+
1560
+ // transpose(inverse(worldToUv * clippingPlaneLocalToWorld))
1561
+ // transpose(inverse(clippingPlaneLocalToWorld) * inverse(worldToUv))
1562
+ // transpose(inverse(clippingPlaneLocalToWorld) * uvToWorld)
1563
+
1564
+ uniforms.clippingPlanesMatrix = Matrix4.transpose(
1565
+ Matrix4.multiplyTransformation(
1566
+ Matrix4.inverse(
1567
+ clippingPlanes.modelMatrix,
1568
+ uniforms.clippingPlanesMatrix
1569
+ ),
1570
+ primitive._transformPositionUvToWorld,
1571
+ uniforms.clippingPlanesMatrix
1572
+ ),
1573
+ uniforms.clippingPlanesMatrix
1574
+ );
1575
+ }
1576
+
1577
+ if (
1578
+ primitive._clippingPlanesState === clippingPlanesState &&
1579
+ primitive._clippingPlanesEnabled === enabled
1580
+ ) {
1581
+ return false;
1582
+ }
1583
+ primitive._clippingPlanesState = clippingPlanesState;
1584
+ primitive._clippingPlanesEnabled = enabled;
1585
+
1586
+ return true;
1587
+ }
1588
+
1589
+ /**
1590
+ * Returns true if this object was destroyed; otherwise, false.
1591
+ * <br /><br />
1592
+ * If this object was destroyed, it should not be used; calling any function other than
1593
+ * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
1594
+ *
1595
+ * @returns {Boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>.
1596
+ *
1597
+ * @see VoxelPrimitive#destroy
1598
+ */
1599
+ VoxelPrimitive.prototype.isDestroyed = function () {
1600
+ return false;
1601
+ };
1602
+
1603
+ /**
1604
+ * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
1605
+ * release of WebGL resources, instead of relying on the garbage collector to destroy this object.
1606
+ * <br /><br />
1607
+ * Once an object is destroyed, it should not be used; calling any function other than
1608
+ * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
1609
+ * assign the return value (<code>undefined</code>) to the object as done in the example.
1610
+ *
1611
+ * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
1612
+ *
1613
+ * @see VoxelPrimitive#isDestroyed
1614
+ *
1615
+ * @example
1616
+ * voxelPrimitive = voxelPrimitive && voxelPrimitive.destroy();
1617
+ */
1618
+ VoxelPrimitive.prototype.destroy = function () {
1619
+ const drawCommand = this._drawCommand;
1620
+ if (defined(drawCommand)) {
1621
+ drawCommand.shaderProgram =
1622
+ drawCommand.shaderProgram && drawCommand.shaderProgram.destroy();
1623
+ }
1624
+ const drawCommandPick = this._drawCommandPick;
1625
+ if (defined(drawCommandPick)) {
1626
+ drawCommandPick.shaderProgram =
1627
+ drawCommandPick.shaderProgram && drawCommandPick.shaderProgram.destroy();
1628
+ }
1629
+
1630
+ this._pickId = this._pickId && this._pickId.destroy();
1631
+ this._traversal = this._traversal && this._traversal.destroy();
1632
+ this._clippingPlanes = this._clippingPlanes && this._clippingPlanes.destroy();
1633
+
1634
+ return destroyObject(this);
1635
+ };
1636
+
1637
+ const corners = new Array(
1638
+ new Cartesian4(-1.0, -1.0, -1.0, 1.0),
1639
+ new Cartesian4(+1.0, -1.0, -1.0, 1.0),
1640
+ new Cartesian4(-1.0, +1.0, -1.0, 1.0),
1641
+ new Cartesian4(+1.0, +1.0, -1.0, 1.0),
1642
+ new Cartesian4(-1.0, -1.0, +1.0, 1.0),
1643
+ new Cartesian4(+1.0, -1.0, +1.0, 1.0),
1644
+ new Cartesian4(-1.0, +1.0, +1.0, 1.0),
1645
+ new Cartesian4(+1.0, +1.0, +1.0, 1.0)
1646
+ );
1647
+ const vertexNeighborIndices = new Array(
1648
+ 1,
1649
+ 2,
1650
+ 4,
1651
+ 0,
1652
+ 3,
1653
+ 5,
1654
+ 0,
1655
+ 3,
1656
+ 6,
1657
+ 1,
1658
+ 2,
1659
+ 7,
1660
+ 0,
1661
+ 5,
1662
+ 6,
1663
+ 1,
1664
+ 4,
1665
+ 7,
1666
+ 2,
1667
+ 4,
1668
+ 7,
1669
+ 3,
1670
+ 5,
1671
+ 6
1672
+ );
1673
+
1674
+ const scratchCornersClipSpace = new Array(
1675
+ new Cartesian4(),
1676
+ new Cartesian4(),
1677
+ new Cartesian4(),
1678
+ new Cartesian4(),
1679
+ new Cartesian4(),
1680
+ new Cartesian4(),
1681
+ new Cartesian4(),
1682
+ new Cartesian4()
1683
+ );
1684
+
1685
+ /**
1686
+ * Projects all 8 corners of the oriented bounding box to NDC space and finds the
1687
+ * resulting NDC axis aligned bounding box. To avoid projecting a vertex that is
1688
+ * behind the near plane, it uses the intersection point of each of the vertex's
1689
+ * edges against the near plane as part of the AABB calculation. This is done in
1690
+ * clip space prior to perspective division.
1691
+ *
1692
+ * @function
1693
+ *
1694
+ * @param {OrientedBoundingBox} orientedBoundingBox
1695
+ * @param {Matrix4} worldToProjection
1696
+ * @param {Cartesian4} result
1697
+ * @returns {Cartesian4}
1698
+ *
1699
+ * @private
1700
+ */
1701
+ function orientedBoundingBoxToNdcAabb(
1702
+ orientedBoundingBox,
1703
+ worldToProjection,
1704
+ result
1705
+ ) {
1706
+ const transformPositionLocalToWorld = Matrix4.fromRotationTranslation(
1707
+ orientedBoundingBox.halfAxes,
1708
+ orientedBoundingBox.center,
1709
+ scratchTransformPositionLocalToWorld
1710
+ );
1711
+ const transformPositionLocalToProjection = Matrix4.multiply(
1712
+ worldToProjection,
1713
+ transformPositionLocalToWorld,
1714
+ scratchTransformPositionLocalToProjection
1715
+ );
1716
+
1717
+ let ndcMinX = +Number.MAX_VALUE;
1718
+ let ndcMaxX = -Number.MAX_VALUE;
1719
+ let ndcMinY = +Number.MAX_VALUE;
1720
+ let ndcMaxY = -Number.MAX_VALUE;
1721
+ let cornerIndex;
1722
+
1723
+ // Convert all points to clip space
1724
+ const cornersClipSpace = scratchCornersClipSpace;
1725
+ const cornersLength = corners.length;
1726
+ for (cornerIndex = 0; cornerIndex < cornersLength; cornerIndex++) {
1727
+ Matrix4.multiplyByVector(
1728
+ transformPositionLocalToProjection,
1729
+ corners[cornerIndex],
1730
+ cornersClipSpace[cornerIndex]
1731
+ );
1732
+ }
1733
+
1734
+ for (cornerIndex = 0; cornerIndex < cornersLength; cornerIndex++) {
1735
+ const position = cornersClipSpace[cornerIndex];
1736
+ if (position.z >= -position.w) {
1737
+ // Position is past near plane, so there's no need to clip.
1738
+ const ndcX = position.x / position.w;
1739
+ const ndcY = position.y / position.w;
1740
+ ndcMinX = Math.min(ndcMinX, ndcX);
1741
+ ndcMaxX = Math.max(ndcMaxX, ndcX);
1742
+ ndcMinY = Math.min(ndcMinY, ndcY);
1743
+ ndcMaxY = Math.max(ndcMaxY, ndcY);
1744
+ } else {
1745
+ for (let neighborIndex = 0; neighborIndex < 3; neighborIndex++) {
1746
+ const neighborVertexIndex =
1747
+ vertexNeighborIndices[cornerIndex * 3 + neighborIndex];
1748
+ const neighborPosition = cornersClipSpace[neighborVertexIndex];
1749
+ if (neighborPosition.z >= -neighborPosition.w) {
1750
+ // Position is behind the near plane and neighbor is after, so get intersection point on the near plane.
1751
+ const distanceToPlaneFromPosition = position.z + position.w;
1752
+ const distanceToPlaneFromNeighbor =
1753
+ neighborPosition.z + neighborPosition.w;
1754
+ const t =
1755
+ distanceToPlaneFromPosition /
1756
+ (distanceToPlaneFromPosition - distanceToPlaneFromNeighbor);
1757
+
1758
+ const intersect = Cartesian4.lerp(
1759
+ position,
1760
+ neighborPosition,
1761
+ t,
1762
+ scratchIntersect
1763
+ );
1764
+ const intersectNdcX = intersect.x / intersect.w;
1765
+ const intersectNdcY = intersect.y / intersect.w;
1766
+ ndcMinX = Math.min(ndcMinX, intersectNdcX);
1767
+ ndcMaxX = Math.max(ndcMaxX, intersectNdcX);
1768
+ ndcMinY = Math.min(ndcMinY, intersectNdcY);
1769
+ ndcMaxY = Math.max(ndcMaxY, intersectNdcY);
1770
+ }
1771
+ }
1772
+ }
1773
+ }
1774
+
1775
+ // Clamp the NDC values to -1 to +1 range even if they extend much further.
1776
+ ndcMinX = CesiumMath.clamp(ndcMinX, -1.0, +1.0);
1777
+ ndcMinY = CesiumMath.clamp(ndcMinY, -1.0, +1.0);
1778
+ ndcMaxX = CesiumMath.clamp(ndcMaxX, -1.0, +1.0);
1779
+ ndcMaxY = CesiumMath.clamp(ndcMaxY, -1.0, +1.0);
1780
+ result = Cartesian4.fromElements(ndcMinX, ndcMinY, ndcMaxX, ndcMaxY, result);
1781
+
1782
+ return result;
1783
+ }
1784
+
1785
+ const polylineAxisDistance = 30000000.0;
1786
+ const polylineXAxis = new Cartesian3(polylineAxisDistance, 0.0, 0.0);
1787
+ const polylineYAxis = new Cartesian3(0.0, polylineAxisDistance, 0.0);
1788
+ const polylineZAxis = new Cartesian3(0.0, 0.0, polylineAxisDistance);
1789
+
1790
+ /**
1791
+ * Draws the tile bounding boxes and axes.
1792
+ *
1793
+ * @function
1794
+ *
1795
+ * @param {VoxelPrimitive} that
1796
+ * @param {FrameState} frameState
1797
+ *
1798
+ * @private
1799
+ */
1800
+ function debugDraw(that, frameState) {
1801
+ const traversal = that._traversal;
1802
+ const polylines = that._debugPolylines;
1803
+ polylines.removeAll();
1804
+
1805
+ function makePolylineLineSegment(startPos, endPos, color, thickness) {
1806
+ polylines.add({
1807
+ positions: [startPos, endPos],
1808
+ width: thickness,
1809
+ material: Material.fromType("Color", {
1810
+ color: color,
1811
+ }),
1812
+ });
1813
+ }
1814
+
1815
+ function makePolylineBox(orientedBoundingBox, color, thickness) {
1816
+ // Normally would want to use a scratch variable to store the corners, but
1817
+ // polylines don't clone the positions.
1818
+ const corners = orientedBoundingBox.computeCorners();
1819
+ makePolylineLineSegment(corners[0], corners[1], color, thickness);
1820
+ makePolylineLineSegment(corners[2], corners[3], color, thickness);
1821
+ makePolylineLineSegment(corners[4], corners[5], color, thickness);
1822
+ makePolylineLineSegment(corners[6], corners[7], color, thickness);
1823
+ makePolylineLineSegment(corners[0], corners[2], color, thickness);
1824
+ makePolylineLineSegment(corners[4], corners[6], color, thickness);
1825
+ makePolylineLineSegment(corners[1], corners[3], color, thickness);
1826
+ makePolylineLineSegment(corners[5], corners[7], color, thickness);
1827
+ makePolylineLineSegment(corners[0], corners[4], color, thickness);
1828
+ makePolylineLineSegment(corners[2], corners[6], color, thickness);
1829
+ makePolylineLineSegment(corners[1], corners[5], color, thickness);
1830
+ makePolylineLineSegment(corners[3], corners[7], color, thickness);
1831
+ }
1832
+
1833
+ function drawTile(tile) {
1834
+ if (!traversal.isRenderable(tile)) {
1835
+ return;
1836
+ }
1837
+
1838
+ const level = tile.level;
1839
+ const startThickness = 5.0;
1840
+ const thickness = Math.max(1.0, startThickness / Math.pow(2.0, level));
1841
+ const colors = [Color.RED, Color.LIME, Color.BLUE];
1842
+ const color = colors[level % 3];
1843
+
1844
+ makePolylineBox(tile.orientedBoundingBox, color, thickness);
1845
+
1846
+ if (defined(tile.children)) {
1847
+ for (let i = 0; i < 8; i++) {
1848
+ drawTile(tile.children[i]);
1849
+ }
1850
+ }
1851
+ }
1852
+
1853
+ makePolylineBox(that._shape.orientedBoundingBox, Color.WHITE, 5.0);
1854
+
1855
+ drawTile(traversal.rootNode);
1856
+
1857
+ const axisThickness = 10.0;
1858
+ makePolylineLineSegment(
1859
+ Cartesian3.ZERO,
1860
+ polylineXAxis,
1861
+ Color.RED,
1862
+ axisThickness
1863
+ );
1864
+ makePolylineLineSegment(
1865
+ Cartesian3.ZERO,
1866
+ polylineYAxis,
1867
+ Color.LIME,
1868
+ axisThickness
1869
+ );
1870
+ makePolylineLineSegment(
1871
+ Cartesian3.ZERO,
1872
+ polylineZAxis,
1873
+ Color.BLUE,
1874
+ axisThickness
1875
+ );
1876
+
1877
+ polylines.update(frameState);
1878
+ }
1879
+
1880
+ /**
1881
+ * The default custom shader used by the primitive.
1882
+ *
1883
+ * @type {CustomShader}
1884
+ * @constant
1885
+ * @readonly
1886
+ *
1887
+ * @private
1888
+ */
1889
+ VoxelPrimitive.DefaultCustomShader = new CustomShader({
1890
+ fragmentShaderText: `void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material)
1891
+ {
1892
+ material.diffuse = vec3(1.0);
1893
+ material.alpha = 1.0;
1894
+ }`,
1895
+ });
1896
+
1897
+ function DefaultVoxelProvider() {
1898
+ this.ready = true;
1899
+ this.readyPromise = Promise.resolve(this);
1900
+ this.shape = VoxelShapeType.BOX;
1901
+ this.dimensions = new Cartesian3(1, 1, 1);
1902
+ this.names = ["data"];
1903
+ this.types = [MetadataType.SCALAR];
1904
+ this.componentTypes = [MetadataComponentType.FLOAT32];
1905
+ this.maximumTileCount = 1;
1906
+ }
1907
+
1908
+ DefaultVoxelProvider.prototype.requestData = function (options) {
1909
+ const tileLevel = defined(options) ? defaultValue(options.tileLevel, 0) : 0;
1910
+ if (tileLevel >= 1) {
1911
+ return undefined;
1912
+ }
1913
+
1914
+ return Promise.resolve([new Float32Array(1)]);
1915
+ };
1916
+
1917
+ VoxelPrimitive.DefaultProvider = new DefaultVoxelProvider();
1918
+
1919
+ export default VoxelPrimitive;