@cesium/engine 1.0.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.
- package/Build/Workers/{AttributeCompression-4589338a.js → AttributeCompression-b646d393.js} +1 -1
- package/Build/Workers/{AxisAlignedBoundingBox-bfb1234f.js → AxisAlignedBoundingBox-a4321399.js} +1 -1
- package/Build/Workers/{BoundingRectangle-7ffc2153.js → BoundingRectangle-80d8801f.js} +1 -1
- package/Build/Workers/{BoxGeometry-93f344a3.js → BoxGeometry-33c10a4f.js} +1 -1
- package/Build/Workers/{Color-0c5aaf47.js → Color-1bf9a6e0.js} +1 -1
- package/Build/Workers/{CoplanarPolygonGeometryLibrary-6597982a.js → CoplanarPolygonGeometryLibrary-5c5b981b.js} +1 -1
- package/Build/Workers/{CorridorGeometryLibrary-2119580e.js → CorridorGeometryLibrary-7cbae7a0.js} +1 -1
- package/Build/Workers/{CylinderGeometry-f9503c6d.js → CylinderGeometry-42740df0.js} +1 -1
- package/Build/Workers/{EllipseGeometry-fedf72d5.js → EllipseGeometry-49a3ac21.js} +1 -1
- package/Build/Workers/{EllipseGeometryLibrary-4ea68687.js → EllipseGeometryLibrary-b891b2f8.js} +1 -1
- package/Build/Workers/{EllipseOutlineGeometry-e2ae6a35.js → EllipseOutlineGeometry-fbd72e07.js} +1 -1
- package/Build/Workers/{EllipsoidGeodesic-16de63ea.js → EllipsoidGeodesic-98c62a56.js} +1 -1
- package/Build/Workers/{EllipsoidGeometry-95c0330e.js → EllipsoidGeometry-a351dba8.js} +1 -1
- package/Build/Workers/{EllipsoidOutlineGeometry-d6d2ceec.js → EllipsoidOutlineGeometry-3e8779bf.js} +1 -1
- package/Build/Workers/{EllipsoidRhumbLine-ae5e65e0.js → EllipsoidRhumbLine-19756602.js} +1 -1
- package/Build/Workers/{EllipsoidTangentPlane-bfc674bf.js → EllipsoidTangentPlane-cfb50678.js} +1 -1
- package/Build/Workers/{EncodedCartesian3-f473ea18.js → EncodedCartesian3-81f70735.js} +1 -1
- package/Build/Workers/{FrustumGeometry-3bf2e4eb.js → FrustumGeometry-c5754412.js} +1 -1
- package/Build/Workers/{GeometryAttribute-df5f473e.js → GeometryAttribute-0bfd05e8.js} +1 -1
- package/Build/Workers/{GeometryInstance-aa75b4cf.js → GeometryInstance-451dc1cd.js} +1 -1
- package/Build/Workers/{GeometryPipeline-f0e46c42.js → GeometryPipeline-0166905d.js} +1 -1
- package/Build/Workers/{IntersectionTests-9de29d51.js → IntersectionTests-a93d3de9.js} +1 -1
- package/Build/Workers/{Matrix2-ce637455.js → Matrix2-13178034.js} +4 -2
- package/Build/Workers/{Matrix3-4f4df527.js → Matrix3-315394f6.js} +2 -1
- package/Build/Workers/{OrientedBoundingBox-d3ff3d4d.js → OrientedBoundingBox-b450cb61.js} +5 -5
- package/Build/Workers/{Plane-b81241c2.js → Plane-900aa728.js} +1 -1
- package/Build/Workers/{PolygonGeometryLibrary-6f4937bb.js → PolygonGeometryLibrary-f918ac26.js} +1 -1
- package/Build/Workers/PolygonPipeline-f59a8f0a.js +1345 -0
- package/Build/Workers/{PolylinePipeline-2e2b015c.js → PolylinePipeline-d8e6bd9b.js} +1 -1
- package/Build/Workers/{PolylineVolumeGeometryLibrary-7ee1d449.js → PolylineVolumeGeometryLibrary-125d2edf.js} +1 -1
- package/Build/Workers/{PrimitivePipeline-a9b7aae0.js → PrimitivePipeline-0d7b5ed4.js} +1 -1
- package/Build/Workers/{RectangleGeometryLibrary-9aa6c8f6.js → RectangleGeometryLibrary-0768db63.js} +1 -1
- package/Build/Workers/{TerrainEncoding-b52dcfc5.js → TerrainEncoding-06470d7f.js} +1 -1
- package/Build/Workers/{Transforms-2f755df8.js → Transforms-26539bce.js} +97 -83
- package/Build/Workers/{WallGeometryLibrary-ab19a93d.js → WallGeometryLibrary-6167b0fc.js} +1 -1
- package/Build/Workers/{WebMercatorProjection-9f25de49.js → WebMercatorProjection-13a90d41.js} +1 -1
- package/Build/Workers/cesiumWorkerBootstrapper.js +25 -1
- package/Build/Workers/combineGeometry.js +1 -1
- package/Build/Workers/createBoxGeometry.js +1 -1
- package/Build/Workers/createBoxOutlineGeometry.js +1 -1
- package/Build/Workers/createCircleGeometry.js +1 -1
- package/Build/Workers/createCircleOutlineGeometry.js +1 -1
- package/Build/Workers/createCoplanarPolygonGeometry.js +1 -1
- package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +1 -1
- package/Build/Workers/createCorridorGeometry.js +1 -1
- package/Build/Workers/createCorridorOutlineGeometry.js +1 -1
- package/Build/Workers/createCylinderGeometry.js +1 -1
- package/Build/Workers/createCylinderOutlineGeometry.js +1 -1
- package/Build/Workers/createEllipseGeometry.js +1 -1
- package/Build/Workers/createEllipseOutlineGeometry.js +1 -1
- package/Build/Workers/createEllipsoidGeometry.js +1 -1
- package/Build/Workers/createEllipsoidOutlineGeometry.js +1 -1
- package/Build/Workers/createFrustumGeometry.js +1 -1
- package/Build/Workers/createFrustumOutlineGeometry.js +1 -1
- package/Build/Workers/createGeometry.js +1 -1
- package/Build/Workers/createGroundPolylineGeometry.js +1 -1
- package/Build/Workers/createPlaneGeometry.js +1 -1
- package/Build/Workers/createPlaneOutlineGeometry.js +1 -1
- package/Build/Workers/createPolygonGeometry.js +1 -1
- package/Build/Workers/createPolygonOutlineGeometry.js +1 -1
- package/Build/Workers/createPolylineGeometry.js +1 -1
- package/Build/Workers/createPolylineVolumeGeometry.js +1 -1
- package/Build/Workers/createPolylineVolumeOutlineGeometry.js +1 -1
- package/Build/Workers/createRectangleGeometry.js +1 -1
- package/Build/Workers/createRectangleOutlineGeometry.js +1 -1
- package/Build/Workers/createSimplePolylineGeometry.js +1 -1
- package/Build/Workers/createSphereGeometry.js +1 -1
- package/Build/Workers/createSphereOutlineGeometry.js +1 -1
- package/Build/Workers/createVectorTileClampedPolylines.js +1 -1
- package/Build/Workers/createVectorTileGeometries.js +1 -1
- package/Build/Workers/createVectorTilePoints.js +1 -1
- package/Build/Workers/createVectorTilePolygons.js +1 -1
- package/Build/Workers/createVectorTilePolylines.js +1 -1
- package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +1 -1
- package/Build/Workers/createVerticesFromHeightmap.js +7 -3
- package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +1 -1
- package/Build/Workers/createWallGeometry.js +1 -1
- package/Build/Workers/createWallOutlineGeometry.js +1 -1
- package/Build/Workers/decodeI3S.js +1 -1
- package/Build/Workers/package.js +25 -1
- package/Build/Workers/transferTypedArrayTest.js +25 -1
- package/Build/Workers/upsampleQuantizedTerrainMesh.js +1 -1
- package/Source/Core/EarthOrientationParameters.js +67 -63
- package/Source/Core/Ion.js +1 -1
- package/Source/Core/Matrix2.js +2 -1
- package/Source/Core/Matrix3.js +2 -1
- package/Source/Core/Matrix4.js +1 -0
- package/Source/Core/OrientedBoundingBox.js +4 -4
- package/Source/Core/S2Cell.js +3 -3
- package/Source/Core/Transforms.js +3 -7
- package/Source/DataSources/GpxDataSource.js +4 -6
- package/Source/DataSources/KmlDataSource.js +3 -5
- package/Source/Renderer/Context.js +27 -9
- package/Source/Renderer/Pass.js +3 -2
- package/Source/Scene/Cesium3DTileContentType.js +19 -0
- package/Source/Scene/Cesium3DTilesVoxelProvider.js +482 -0
- package/Source/Scene/Cesium3DTilesetMetadata.js +2 -2
- package/Source/Scene/ContentMetadata.js +2 -2
- package/Source/Scene/DerivedCommand.js +7 -0
- package/Source/Scene/Expression.js +1 -1
- package/Source/Scene/Globe.js +10 -0
- package/Source/Scene/GlobeSurfaceTileProvider.js +7 -0
- package/Source/Scene/GltfImageLoader.js +1 -1
- package/Source/Scene/GltfVertexBufferLoader.js +10 -2
- package/Source/Scene/GroupMetadata.js +2 -2
- package/Source/Scene/ImplicitMetadataView.js +2 -2
- package/Source/Scene/ImplicitSubtreeCache.js +127 -0
- package/Source/Scene/ImplicitSubtreeMetadata.js +2 -2
- package/Source/Scene/ImplicitTileset.js +3 -2
- package/Source/Scene/KeyframeNode.js +47 -0
- package/Source/Scene/Megatexture.js +490 -0
- package/Source/Scene/MetadataClass.js +60 -25
- package/Source/Scene/MetadataClassProperty.js +132 -68
- package/Source/Scene/MetadataComponentType.js +78 -57
- package/Source/Scene/MetadataEnum.js +59 -23
- package/Source/Scene/MetadataEnumValue.js +49 -15
- package/Source/Scene/MetadataSchema.js +53 -24
- package/Source/Scene/MetadataSchemaLoader.js +2 -2
- package/Source/Scene/MetadataTableProperty.js +2 -2
- package/Source/Scene/MetadataType.js +6 -14
- package/Source/Scene/Model/GeoJsonLoader.js +1 -1
- package/Source/Scene/Model/Model.js +2 -3
- package/Source/Scene/Model/buildDrawCommand.js +19 -11
- package/Source/Scene/PointCloud.js +1 -1
- package/Source/Scene/PropertyAttribute.js +2 -2
- package/Source/Scene/PropertyAttributeProperty.js +2 -2
- package/Source/Scene/PropertyTable.js +2 -2
- package/Source/Scene/PropertyTexture.js +2 -2
- package/Source/Scene/PropertyTextureProperty.js +2 -2
- package/Source/Scene/ResourceCache.js +9 -1
- package/Source/Scene/ResourceCacheKey.js +9 -1
- package/Source/Scene/Scene.js +17 -0
- package/Source/Scene/SpatialNode.js +375 -0
- package/Source/Scene/StructuralMetadata.js +2 -2
- package/Source/Scene/TileMetadata.js +2 -2
- package/Source/Scene/TilesetMetadata.js +2 -2
- package/Source/Scene/VoxelBoxShape.js +527 -0
- package/Source/Scene/VoxelContent.js +169 -0
- package/Source/Scene/VoxelCylinderShape.js +937 -0
- package/Source/Scene/VoxelEllipsoidShape.js +937 -0
- package/Source/Scene/VoxelPrimitive.js +1919 -0
- package/Source/Scene/VoxelProvider.js +255 -0
- package/Source/Scene/VoxelRenderResources.js +224 -0
- package/Source/Scene/VoxelShape.js +152 -0
- package/Source/Scene/VoxelShapeType.js +105 -0
- package/Source/Scene/VoxelTraversal.js +1144 -0
- package/Source/Scene/buildVoxelDrawCommands.js +116 -0
- package/Source/Scene/parseBatchTable.js +18 -2
- package/Source/Scene/preprocess3DTileContent.js +8 -0
- package/Source/Scene/processVoxelProperties.js +455 -0
- package/Source/Shaders/BillboardCollectionVS.glsl +1 -1
- package/Source/Shaders/BillboardCollectionVS.js +1 -1
- package/Source/Shaders/Builtin/Constants/passOverlay.glsl +1 -1
- package/Source/Shaders/Builtin/Constants/passOverlay.js +1 -1
- package/Source/Shaders/Builtin/Constants/passVoxels.glsl +9 -0
- package/Source/Shaders/Builtin/Constants/passVoxels.js +11 -0
- package/Source/Shaders/Builtin/CzmBuiltins.js +17 -15
- package/Source/Shaders/Builtin/Functions/windowToEyeCoordinates.glsl +55 -43
- package/Source/Shaders/Builtin/Functions/windowToEyeCoordinates.js +55 -43
- package/Source/Shaders/GlobeFS.glsl +2 -1
- package/Source/Shaders/GlobeFS.js +2 -1
- package/Source/Shaders/PointPrimitiveCollectionVS.glsl +5 -2
- package/Source/Shaders/PointPrimitiveCollectionVS.js +5 -2
- package/Source/Shaders/Voxels/IntersectBox.glsl +79 -0
- package/Source/Shaders/Voxels/IntersectBox.js +81 -0
- package/Source/Shaders/Voxels/IntersectClippingPlanes.glsl +70 -0
- package/Source/Shaders/Voxels/IntersectClippingPlanes.js +72 -0
- package/Source/Shaders/Voxels/IntersectCylinder.glsl +273 -0
- package/Source/Shaders/Voxels/IntersectCylinder.js +275 -0
- package/Source/Shaders/Voxels/IntersectDepth.glsl +23 -0
- package/Source/Shaders/Voxels/IntersectDepth.js +25 -0
- package/Source/Shaders/Voxels/IntersectEllipsoid.glsl +337 -0
- package/Source/Shaders/Voxels/IntersectEllipsoid.js +339 -0
- package/Source/Shaders/Voxels/Intersection.glsl +54 -0
- package/Source/Shaders/Voxels/Intersection.js +56 -0
- package/Source/Shaders/Voxels/IntersectionUtils.glsl +151 -0
- package/Source/Shaders/Voxels/IntersectionUtils.js +153 -0
- package/Source/Shaders/Voxels/Megatexture.glsl +136 -0
- package/Source/Shaders/Voxels/Megatexture.js +138 -0
- package/Source/Shaders/Voxels/Octree.glsl +221 -0
- package/Source/Shaders/Voxels/Octree.js +223 -0
- package/Source/Shaders/Voxels/VoxelFS.glsl +150 -0
- package/Source/Shaders/Voxels/VoxelFS.js +152 -0
- package/Source/Shaders/Voxels/VoxelVS.glsl +11 -0
- package/Source/Shaders/Voxels/VoxelVS.js +13 -0
- package/Source/Shaders/Voxels/convertUvToBox.glsl +16 -0
- package/Source/Shaders/Voxels/convertUvToBox.js +18 -0
- package/Source/Shaders/Voxels/convertUvToCylinder.glsl +79 -0
- package/Source/Shaders/Voxels/convertUvToCylinder.js +81 -0
- package/Source/Shaders/Voxels/convertUvToEllipsoid.glsl +133 -0
- package/Source/Shaders/Voxels/convertUvToEllipsoid.js +135 -0
- package/Source/ThirdParty/Workers/z-worker-pako.js +0 -0
- package/index.d.ts +3124 -2287
- package/index.js +1117 -1085
- package/package.json +3 -4
- 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;
|