@cesium/engine 18.0.0 → 18.2.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/{chunk-QN7JEOQV.js → chunk-2QPO2E4E.js} +5 -5
- package/Build/Workers/{chunk-HS76VTVY.js → chunk-3JKMJ2DT.js} +2 -2
- package/Build/Workers/{chunk-3RKVDGRF.js → chunk-3RZFU3BO.js} +8 -8
- package/Build/Workers/{chunk-4MIY63FM.js → chunk-3X2BQHN6.js} +13 -13
- package/Build/Workers/{chunk-I3BAKR4S.js → chunk-4TGW7D6G.js} +16 -16
- package/Build/Workers/{chunk-LWJWWCZ4.js → chunk-5J3B5IYT.js} +6 -6
- package/Build/Workers/{chunk-WYCR5DWQ.js → chunk-5N52XJIS.js} +2 -2
- package/Build/Workers/{chunk-KGXTCGX3.js → chunk-5WXKC7TN.js} +12 -12
- package/Build/Workers/{chunk-5OL6XFNS.js → chunk-7252BLXK.js} +1 -1
- package/Build/Workers/{chunk-WGHUCZMX.js → chunk-7DRP5IKA.js} +7 -7
- package/Build/Workers/{chunk-AEGAQ6FD.js → chunk-AGEQBE2G.js} +12 -12
- package/Build/Workers/{chunk-EXEZHW3P.js → chunk-AJWIQQTX.js} +4 -4
- package/Build/Workers/{chunk-4DSTDGY3.js → chunk-DBPLDHPT.js} +2 -2
- package/Build/Workers/{chunk-J4MAVE6J.js → chunk-EG3P66JO.js} +6 -6
- package/Build/Workers/{chunk-OATG6PKE.js → chunk-EJGJUZST.js} +12 -12
- package/Build/Workers/{chunk-ZIP27IX6.js → chunk-ER7SSBHR.js} +6 -6
- package/Build/Workers/{chunk-5WVF4BK7.js → chunk-F3ZH4MQG.js} +5 -5
- package/Build/Workers/{chunk-RWFYLWSF.js → chunk-FC2YDGY6.js} +9 -9
- package/Build/Workers/{chunk-NR7KSD56.js → chunk-FPJWHB5J.js} +3 -3
- package/Build/Workers/{chunk-YV37YFUM.js → chunk-HMYDBCCY.js} +9 -9
- package/Build/Workers/{chunk-EHB2OCQX.js → chunk-JVHONLHD.js} +4 -4
- package/Build/Workers/{chunk-ZADJ6FRX.js → chunk-K65RSNI5.js} +4 -4
- package/Build/Workers/{chunk-MFGVMUN3.js → chunk-KZ752MAA.js} +5 -5
- package/Build/Workers/{chunk-CES6DHHV.js → chunk-LMDJ23I7.js} +1 -1
- package/Build/Workers/{chunk-KNA65INJ.js → chunk-LQQDQHA5.js} +4 -4
- package/Build/Workers/{chunk-LZFUG3GO.js → chunk-MATVBVGM.js} +10 -10
- package/Build/Workers/chunk-MIMOEYBO.js +280 -0
- package/Build/Workers/{chunk-NWSAYFZG.js → chunk-MPNN7PNO.js} +6 -6
- package/Build/Workers/{chunk-2AXPWBJG.js → chunk-MV5UVSOZ.js} +1 -1
- package/Build/Workers/{chunk-NVJ5JRIM.js → chunk-NCW6XN5X.js} +2 -2
- package/Build/Workers/{chunk-T6B6H3GR.js → chunk-PFZ45265.js} +7 -7
- package/Build/Workers/{chunk-F4ZAKN4V.js → chunk-PHIB2ITA.js} +2 -2
- package/Build/Workers/{chunk-UK33ZN4K.js → chunk-PLM7GGHT.js} +4 -4
- package/Build/Workers/{chunk-GS55WTRX.js → chunk-PMNYUVMK.js} +6 -6
- package/Build/Workers/{chunk-SIOVJ4L5.js → chunk-R3VU4BBN.js} +4 -4
- package/Build/Workers/{chunk-JF4IYQYC.js → chunk-R7LO2ZW7.js} +7 -7
- package/Build/Workers/{chunk-LIPZUYNR.js → chunk-R7VDSCQM.js} +11 -11
- package/Build/Workers/{chunk-2CAYUY2B.js → chunk-RRSRPDQN.js} +8 -8
- package/Build/Workers/{chunk-IWGMVQGG.js → chunk-SOLM3ZIV.js} +9 -9
- package/Build/Workers/{chunk-W6CPO62M.js → chunk-UGKOGDMZ.js} +6 -6
- package/Build/Workers/{chunk-2QNKQVUT.js → chunk-UGWI4JAZ.js} +5 -5
- package/Build/Workers/{chunk-FPYBD2P5.js → chunk-UOU6BW5C.js} +1 -1
- package/Build/Workers/{chunk-DINSLSJD.js → chunk-USCHXXVF.js} +6 -6
- package/Build/Workers/{chunk-GM55YFOB.js → chunk-VB7MVZDU.js} +14 -14
- package/Build/Workers/{chunk-OIHAAHBK.js → chunk-VC5NTCLG.js} +10 -10
- package/Build/Workers/{chunk-2NKHPWDY.js → chunk-VGOLRLK7.js} +12 -12
- package/Build/Workers/{chunk-QUSP3NWA.js → chunk-VKMJSSOD.js} +5 -5
- package/Build/Workers/{chunk-WTFZHPUW.js → chunk-XAP7YXEJ.js} +5 -5
- package/Build/Workers/{chunk-IWZK2AIH.js → chunk-XH4DQCNS.js} +5 -5
- package/Build/Workers/{chunk-GAUF4F5A.js → chunk-YTIUL27M.js} +16 -16
- package/Build/Workers/{chunk-VGJSKEIB.js → chunk-Z43MDFLH.js} +4 -4
- package/Build/Workers/{chunk-HQE7KSR4.js → chunk-ZT5GZ75Z.js} +2 -2
- package/Build/Workers/combineGeometry.js +21 -21
- package/Build/Workers/createBoxGeometry.js +15 -15
- package/Build/Workers/createBoxOutlineGeometry.js +13 -13
- package/Build/Workers/createCircleGeometry.js +23 -23
- package/Build/Workers/createCircleOutlineGeometry.js +16 -16
- package/Build/Workers/createCoplanarPolygonGeometry.js +30 -30
- package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +28 -28
- package/Build/Workers/createCorridorGeometry.js +26 -26
- package/Build/Workers/createCorridorOutlineGeometry.js +25 -25
- package/Build/Workers/createCylinderGeometry.js +17 -17
- package/Build/Workers/createCylinderOutlineGeometry.js +15 -15
- package/Build/Workers/createEllipseGeometry.js +23 -23
- package/Build/Workers/createEllipseOutlineGeometry.js +16 -16
- package/Build/Workers/createEllipsoidGeometry.js +16 -16
- package/Build/Workers/createEllipsoidOutlineGeometry.js +15 -15
- package/Build/Workers/createFrustumGeometry.js +15 -15
- package/Build/Workers/createFrustumOutlineGeometry.js +15 -15
- package/Build/Workers/createGeometry.js +23 -21
- package/Build/Workers/createGroundPolylineGeometry.js +19 -19
- package/Build/Workers/createPlaneGeometry.js +13 -13
- package/Build/Workers/createPlaneOutlineGeometry.js +12 -12
- package/Build/Workers/createPolygonGeometry.js +29 -29
- package/Build/Workers/createPolygonOutlineGeometry.js +27 -27
- package/Build/Workers/createPolylineGeometry.js +22 -22
- package/Build/Workers/createPolylineVolumeGeometry.js +28 -28
- package/Build/Workers/createPolylineVolumeOutlineGeometry.js +24 -24
- package/Build/Workers/createRectangleGeometry.js +24 -24
- package/Build/Workers/createRectangleOutlineGeometry.js +17 -17
- package/Build/Workers/createSimplePolylineGeometry.js +20 -20
- package/Build/Workers/createSphereGeometry.js +16 -16
- package/Build/Workers/createSphereOutlineGeometry.js +15 -15
- package/Build/Workers/createTaskProcessorWorker.js +3 -3
- package/Build/Workers/createVectorTileClampedPolylines.js +12 -12
- package/Build/Workers/createVectorTileGeometries.js +21 -21
- package/Build/Workers/createVectorTilePoints.js +11 -11
- package/Build/Workers/createVectorTilePolygons.js +19 -19
- package/Build/Workers/createVectorTilePolylines.js +12 -12
- package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +19 -19
- package/Build/Workers/createVerticesFromHeightmap.js +19 -19
- package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +16 -16
- package/Build/Workers/createWallGeometry.js +21 -21
- package/Build/Workers/createWallOutlineGeometry.js +20 -20
- package/Build/Workers/decodeDraco.js +10 -10
- package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +5 -5
- package/Build/Workers/decodeI3S.js +9 -9
- package/Build/Workers/gaussianSplatSorter.js +62 -0
- package/Build/Workers/gaussianSplatTextureGenerator.js +68 -0
- package/Build/Workers/transcodeKTX2.js +59 -7
- package/Build/Workers/transferTypedArrayTest.js +1 -1
- package/Build/Workers/upsampleQuantizedTerrainMesh.js +19 -19
- package/Source/Core/PixelFormat.js +62 -0
- package/Source/Renderer/Context.js +2 -0
- package/Source/Renderer/Pass.js +3 -2
- package/Source/Renderer/Texture.js +1 -0
- package/Source/Renderer/VertexArray.js +33 -8
- package/Source/Renderer/createUniform.js +2 -0
- package/Source/Scene/Cesium3DTileContentFactory.js +23 -0
- package/Source/Scene/Cesium3DTileset.js +59 -2
- package/Source/Scene/GaussianSplat3DTileContent.js +504 -0
- package/Source/Scene/GaussianSplatPrimitive.js +932 -0
- package/Source/Scene/GaussianSplatRenderResources.js +81 -0
- package/Source/Scene/GaussianSplatSorter.js +73 -0
- package/Source/Scene/GaussianSplatTextureGenerator.js +64 -0
- package/Source/Scene/GltfLoader.js +82 -4
- package/Source/Scene/GltfSpzLoader.js +222 -0
- package/Source/Scene/GltfVertexBufferLoader.js +98 -3
- package/Source/Scene/Model/ModelRuntimePrimitive.js +1 -0
- package/Source/Scene/Model/ModelUtility.js +2 -0
- package/Source/Scene/PrimitiveLoadPlan.js +59 -0
- package/Source/Scene/ResourceCache.js +60 -3
- package/Source/Scene/ResourceCacheKey.js +39 -1
- package/Source/Scene/Scene.js +32 -1
- package/Source/Scene/VertexAttributeSemantic.js +30 -0
- package/Source/Shaders/Builtin/Constants/passGaussianSplats.glsl +9 -0
- package/Source/Shaders/Builtin/Constants/passGaussianSplats.js +11 -0
- package/Source/Shaders/Builtin/Constants/passOverlay.glsl +1 -1
- package/Source/Shaders/Builtin/Constants/passOverlay.js +1 -1
- package/Source/Shaders/Builtin/CzmBuiltins.js +2 -0
- package/Source/Shaders/Model/ModelFS.glsl +3 -1
- package/Source/Shaders/Model/ModelFS.js +3 -1
- package/Source/Shaders/Model/ModelVS.glsl +1 -1
- package/Source/Shaders/Model/ModelVS.js +1 -1
- package/Source/Shaders/Model/PointCloudStylingStageVS.glsl +1 -1
- package/Source/Shaders/Model/PointCloudStylingStageVS.js +2 -1
- package/Source/Shaders/PrimitiveGaussianSplatFS.glsl +18 -0
- package/Source/Shaders/PrimitiveGaussianSplatFS.js +20 -0
- package/Source/Shaders/PrimitiveGaussianSplatVS.glsl +108 -0
- package/Source/Shaders/PrimitiveGaussianSplatVS.js +109 -0
- package/Source/ThirdParty/wasm_splats_bg.wasm +0 -0
- package/Source/Workers/gaussianSplatSorter.js +34 -0
- package/Source/Workers/gaussianSplatTextureGenerator.js +39 -0
- package/index.d.ts +16 -0
- package/index.js +71 -62
- package/package.json +4 -2
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import ShaderBuilder from "../Renderer/ShaderBuilder.js";
|
|
2
|
+
import RenderState from "../Renderer/RenderState.js";
|
|
3
|
+
import DepthFunction from "../Scene/DepthFunction.js";
|
|
4
|
+
import ModelAlphaOptions from "./Model/ModelAlphaOptions.js";
|
|
5
|
+
import ShaderDestination from "../Renderer/ShaderDestination.js";
|
|
6
|
+
|
|
7
|
+
function GaussianSplatRenderResources(primitive) {
|
|
8
|
+
const shaderBuilder = new ShaderBuilder();
|
|
9
|
+
/**
|
|
10
|
+
* An object used to build a shader incrementally. Each pipeline stage
|
|
11
|
+
* may add lines of shader code to this object.
|
|
12
|
+
*
|
|
13
|
+
* @type {ShaderBuilder}
|
|
14
|
+
* @readonly
|
|
15
|
+
*
|
|
16
|
+
* @private
|
|
17
|
+
*/
|
|
18
|
+
this.shaderBuilder = shaderBuilder;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* A dictionary mapping uniform name to functions that return the uniform
|
|
22
|
+
* values.
|
|
23
|
+
*
|
|
24
|
+
* @type {Object<string, Function>}
|
|
25
|
+
* @readonly
|
|
26
|
+
*
|
|
27
|
+
* @private
|
|
28
|
+
*/
|
|
29
|
+
this.uniformMap = {};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* An object storing options for creating a {@link RenderState}.
|
|
33
|
+
* The pipeline stages simply set the options, the render state is created
|
|
34
|
+
* when the {@link DrawCommand} is constructed.
|
|
35
|
+
*
|
|
36
|
+
* @type {object}
|
|
37
|
+
* @readonly
|
|
38
|
+
*
|
|
39
|
+
* @private
|
|
40
|
+
*/
|
|
41
|
+
this.renderStateOptions = RenderState.getState(
|
|
42
|
+
RenderState.fromCache({
|
|
43
|
+
depthTest: {
|
|
44
|
+
enabled: true,
|
|
45
|
+
func: DepthFunction.LESS_OR_EQUAL,
|
|
46
|
+
},
|
|
47
|
+
}),
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Options for configuring the alpha stage such as pass and alpha cutoff.
|
|
52
|
+
*
|
|
53
|
+
* @type {ModelAlphaOptions}
|
|
54
|
+
* @readonly
|
|
55
|
+
*
|
|
56
|
+
* @private
|
|
57
|
+
*/
|
|
58
|
+
this.alphaOptions = new ModelAlphaOptions();
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Whether the model is part of a tileset that uses the skipLevelOfDetail
|
|
62
|
+
* optimization. This value indicates what draw commands are needed and
|
|
63
|
+
* is set by TilesetPipelineStage.
|
|
64
|
+
*
|
|
65
|
+
* @type {boolean}
|
|
66
|
+
* @default false
|
|
67
|
+
*
|
|
68
|
+
* @private
|
|
69
|
+
*/
|
|
70
|
+
this.hasSkipLevelOfDetail = false;
|
|
71
|
+
|
|
72
|
+
if (primitive._useLogDepth) {
|
|
73
|
+
shaderBuilder.addDefine(
|
|
74
|
+
"LOG_DEPTH_READ_ONLY",
|
|
75
|
+
undefined,
|
|
76
|
+
ShaderDestination.FRAGMENT,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export default GaussianSplatRenderResources;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import defined from "../Core/defined.js";
|
|
2
|
+
import FeatureDetection from "../Core/FeatureDetection.js";
|
|
3
|
+
import RuntimeError from "../Core/RuntimeError.js";
|
|
4
|
+
import TaskProcessor from "../Core/TaskProcessor.js";
|
|
5
|
+
|
|
6
|
+
/** * A sorter for Gaussian splats that uses a task processor to handle sorting in parallel.
|
|
7
|
+
* This class is responsible for initializing the task processor and scheduling sorting tasks.
|
|
8
|
+
* * @constructor
|
|
9
|
+
* @private
|
|
10
|
+
*/
|
|
11
|
+
function GaussianSplatSorter() {}
|
|
12
|
+
|
|
13
|
+
GaussianSplatSorter._maxSortingConcurrency = Math.max(
|
|
14
|
+
FeatureDetection.hardwareConcurrency - 1,
|
|
15
|
+
1,
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
GaussianSplatSorter._sorterTaskProcessor = undefined;
|
|
19
|
+
GaussianSplatSorter._taskProcessorReady = false;
|
|
20
|
+
GaussianSplatSorter._error = undefined;
|
|
21
|
+
GaussianSplatSorter._getSorterTaskProcessor = function () {
|
|
22
|
+
if (!defined(GaussianSplatSorter._sorterTaskProcessor)) {
|
|
23
|
+
const processor = new TaskProcessor(
|
|
24
|
+
"gaussianSplatSorter",
|
|
25
|
+
GaussianSplatSorter._maxSortingConcurrency,
|
|
26
|
+
);
|
|
27
|
+
processor
|
|
28
|
+
.initWebAssemblyModule({
|
|
29
|
+
wasmBinaryFile: "ThirdParty/wasm_splats_bg.wasm",
|
|
30
|
+
})
|
|
31
|
+
.then(function (result) {
|
|
32
|
+
if (result) {
|
|
33
|
+
GaussianSplatSorter._taskProcessorReady = true;
|
|
34
|
+
} else {
|
|
35
|
+
GaussianSplatSorter._error = new RuntimeError(
|
|
36
|
+
"Gaussian splat sorter could not be initialized.",
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
.catch((error) => {
|
|
41
|
+
GaussianSplatSorter._error = error;
|
|
42
|
+
});
|
|
43
|
+
GaussianSplatSorter._sorterTaskProcessor = processor;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return GaussianSplatSorter._sorterTaskProcessor;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Sorts Gaussian splats using a radix sort algorithm. Sorted by distance from the camera.
|
|
50
|
+
* A new list of indexes is returned, which can be used to render the splats in the correct order.
|
|
51
|
+
*
|
|
52
|
+
* @param {Object} parameters - The parameters for sorting Gaussian splat indexes.
|
|
53
|
+
* @param {Object} parameters.primitive - The primitive containing positions and modelView matrices.
|
|
54
|
+
* @returns {Promise|undefined} A promise that resolves to the sorted indexes or undefined if the task cannot be scheduled.
|
|
55
|
+
* @exception {RuntimeError} Sorter could not be initialized.
|
|
56
|
+
* @private
|
|
57
|
+
*/
|
|
58
|
+
GaussianSplatSorter.radixSortIndexes = function (parameters) {
|
|
59
|
+
const sorterTaskProcessor = GaussianSplatSorter._getSorterTaskProcessor();
|
|
60
|
+
if (defined(GaussianSplatSorter._error)) {
|
|
61
|
+
throw GaussianSplatSorter._error;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (!GaussianSplatSorter._taskProcessorReady) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return sorterTaskProcessor.scheduleTask(parameters, [
|
|
69
|
+
parameters.primitive.positions.buffer,
|
|
70
|
+
]);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default GaussianSplatSorter;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import defined from "../Core/defined.js";
|
|
2
|
+
import FeatureDetection from "../Core/FeatureDetection.js";
|
|
3
|
+
import RuntimeError from "../Core/RuntimeError.js";
|
|
4
|
+
import TaskProcessor from "../Core/TaskProcessor.js";
|
|
5
|
+
|
|
6
|
+
function GaussianSplatTextureGenerator() {}
|
|
7
|
+
|
|
8
|
+
GaussianSplatTextureGenerator._maxSortingConcurrency = Math.max(
|
|
9
|
+
FeatureDetection.hardwareConcurrency - 1,
|
|
10
|
+
1,
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
GaussianSplatTextureGenerator._textureTaskProcessor = undefined;
|
|
14
|
+
GaussianSplatTextureGenerator._taskProcessorReady = false;
|
|
15
|
+
GaussianSplatTextureGenerator._error = undefined;
|
|
16
|
+
GaussianSplatTextureGenerator._getTextureTaskProcessor = function () {
|
|
17
|
+
if (!defined(GaussianSplatTextureGenerator._textureTaskProcessor)) {
|
|
18
|
+
const processor = new TaskProcessor(
|
|
19
|
+
"gaussianSplatTextureGenerator",
|
|
20
|
+
GaussianSplatTextureGenerator._maxSortingConcurrency,
|
|
21
|
+
);
|
|
22
|
+
processor
|
|
23
|
+
.initWebAssemblyModule({
|
|
24
|
+
wasmBinaryFile: "ThirdParty/wasm_splats_bg.wasm",
|
|
25
|
+
})
|
|
26
|
+
.then(function (result) {
|
|
27
|
+
if (result) {
|
|
28
|
+
GaussianSplatTextureGenerator._taskProcessorReady = true;
|
|
29
|
+
} else {
|
|
30
|
+
GaussianSplatTextureGenerator._error = new RuntimeError(
|
|
31
|
+
"Gaussian splat sorter could not be initialized.",
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
.catch((error) => {
|
|
36
|
+
GaussianSplatTextureGenerator._error = error;
|
|
37
|
+
});
|
|
38
|
+
GaussianSplatTextureGenerator._textureTaskProcessor = processor;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return GaussianSplatTextureGenerator._textureTaskProcessor;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
GaussianSplatTextureGenerator.generateFromAttributes = function (parameters) {
|
|
45
|
+
const textureTaskProcessor =
|
|
46
|
+
GaussianSplatTextureGenerator._getTextureTaskProcessor();
|
|
47
|
+
if (defined(GaussianSplatTextureGenerator._error)) {
|
|
48
|
+
throw GaussianSplatTextureGenerator._error;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (!GaussianSplatTextureGenerator._taskProcessorReady) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const { attributes } = parameters;
|
|
56
|
+
return textureTaskProcessor.scheduleTask(parameters, [
|
|
57
|
+
attributes.positions.buffer,
|
|
58
|
+
attributes.scales.buffer,
|
|
59
|
+
attributes.rotations.buffer,
|
|
60
|
+
attributes.colors.buffer,
|
|
61
|
+
]);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export default GaussianSplatTextureGenerator;
|
|
@@ -507,8 +507,7 @@ function postProcessGeometry(loader, context) {
|
|
|
507
507
|
for (let i = 0; i < loadPlans.length; i++) {
|
|
508
508
|
const loadPlan = loadPlans[i];
|
|
509
509
|
loadPlan.postProcess(context);
|
|
510
|
-
|
|
511
|
-
if (loadPlan.needsOutlines) {
|
|
510
|
+
if (loadPlan.needsOutlines || loadPlan.needsGaussianSplats) {
|
|
512
511
|
// The glTF loader takes ownership of any buffers generated in the
|
|
513
512
|
// post-process stage since they were created after the geometry loaders
|
|
514
513
|
// finished. This way they can be destroyed when the loader is destroyed.
|
|
@@ -687,6 +686,7 @@ function getVertexBufferLoader(
|
|
|
687
686
|
semantic,
|
|
688
687
|
primitive,
|
|
689
688
|
draco,
|
|
689
|
+
spzExtension,
|
|
690
690
|
loadBuffer,
|
|
691
691
|
loadTypedArray,
|
|
692
692
|
frameState,
|
|
@@ -703,6 +703,7 @@ function getVertexBufferLoader(
|
|
|
703
703
|
bufferViewId: bufferViewId,
|
|
704
704
|
primitive: primitive,
|
|
705
705
|
draco: draco,
|
|
706
|
+
spz: spzExtension,
|
|
706
707
|
attributeSemantic: semantic,
|
|
707
708
|
accessorId: accessorId,
|
|
708
709
|
asynchronous: loader._asynchronous,
|
|
@@ -1032,7 +1033,10 @@ function createAttribute(gltf, accessorId, name, semantic, setIndex) {
|
|
|
1032
1033
|
attribute.semantic === VertexAttributeSemantic.POSITION ||
|
|
1033
1034
|
attribute.semantic === VertexAttributeSemantic.NORMAL ||
|
|
1034
1035
|
attribute.semantic === VertexAttributeSemantic.TANGENT ||
|
|
1035
|
-
attribute.semantic === VertexAttributeSemantic.TEXCOORD
|
|
1036
|
+
attribute.semantic === VertexAttributeSemantic.TEXCOORD ||
|
|
1037
|
+
attribute.semantic === VertexAttributeSemantic.FEATURE_ID ||
|
|
1038
|
+
attribute.semantic === VertexAttributeSemantic.SCALE ||
|
|
1039
|
+
attribute.semantic === VertexAttributeSemantic.ROTATION;
|
|
1036
1040
|
|
|
1037
1041
|
// In the glTF 2.0 spec, min and max are not affected by the normalized flag.
|
|
1038
1042
|
// However, for KHR_mesh_quantization, min and max must be dequantized for
|
|
@@ -1124,6 +1128,58 @@ function finalizeDracoAttribute(
|
|
|
1124
1128
|
}
|
|
1125
1129
|
}
|
|
1126
1130
|
|
|
1131
|
+
function finalizeSpzAttribute(
|
|
1132
|
+
attribute,
|
|
1133
|
+
vertexBufferLoader,
|
|
1134
|
+
loadBuffer,
|
|
1135
|
+
loadTypedArray,
|
|
1136
|
+
) {
|
|
1137
|
+
attribute.byteOffset = 0;
|
|
1138
|
+
attribute.byteStride = undefined;
|
|
1139
|
+
|
|
1140
|
+
if (loadBuffer) {
|
|
1141
|
+
attribute.buffer = vertexBufferLoader.buffer;
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
if (loadTypedArray && defined(vertexBufferLoader.typedArray)) {
|
|
1145
|
+
attribute.typedArray = ComponentDatatype.createArrayBufferView(
|
|
1146
|
+
attribute.componentDatatype,
|
|
1147
|
+
vertexBufferLoader.typedArray.buffer,
|
|
1148
|
+
);
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
if (attribute.semantic === VertexAttributeSemantic.POSITION) {
|
|
1152
|
+
const findMinMaxXY = (flatArray) => {
|
|
1153
|
+
let minX = Infinity;
|
|
1154
|
+
let maxX = -Infinity;
|
|
1155
|
+
let minY = Infinity;
|
|
1156
|
+
let maxY = -Infinity;
|
|
1157
|
+
let minZ = Infinity;
|
|
1158
|
+
let maxZ = -Infinity;
|
|
1159
|
+
|
|
1160
|
+
for (let i = 0; i < flatArray.length; i += 3) {
|
|
1161
|
+
const x = flatArray[i];
|
|
1162
|
+
const y = flatArray[i + 1];
|
|
1163
|
+
const z = flatArray[i + 2];
|
|
1164
|
+
|
|
1165
|
+
minX = Math.min(minX, x);
|
|
1166
|
+
maxX = Math.max(maxX, x);
|
|
1167
|
+
minY = Math.min(minY, y);
|
|
1168
|
+
maxY = Math.max(maxY, y);
|
|
1169
|
+
minZ = Math.min(minZ, z);
|
|
1170
|
+
maxZ = Math.max(maxZ, z);
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
return [
|
|
1174
|
+
new Cartesian3(minX, minY, minZ),
|
|
1175
|
+
new Cartesian3(maxX, maxY, maxZ),
|
|
1176
|
+
];
|
|
1177
|
+
};
|
|
1178
|
+
const buffer = attribute.typedArray;
|
|
1179
|
+
[attribute.min, attribute.max] = findMinMaxXY(buffer);
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1127
1183
|
function finalizeAttribute(
|
|
1128
1184
|
gltf,
|
|
1129
1185
|
accessor,
|
|
@@ -1160,6 +1216,7 @@ function loadAttribute(
|
|
|
1160
1216
|
semanticInfo,
|
|
1161
1217
|
primitive,
|
|
1162
1218
|
draco,
|
|
1219
|
+
spz,
|
|
1163
1220
|
loadBuffer,
|
|
1164
1221
|
loadTypedArray,
|
|
1165
1222
|
frameState,
|
|
@@ -1185,7 +1242,7 @@ function loadAttribute(
|
|
|
1185
1242
|
setIndex,
|
|
1186
1243
|
);
|
|
1187
1244
|
|
|
1188
|
-
if (!defined(draco) && !defined(bufferViewId)) {
|
|
1245
|
+
if (!defined(draco) && !defined(bufferViewId) && !defined(spz)) {
|
|
1189
1246
|
return attribute;
|
|
1190
1247
|
}
|
|
1191
1248
|
|
|
@@ -1195,6 +1252,7 @@ function loadAttribute(
|
|
|
1195
1252
|
gltfSemantic,
|
|
1196
1253
|
primitive,
|
|
1197
1254
|
draco,
|
|
1255
|
+
spz,
|
|
1198
1256
|
loadBuffer,
|
|
1199
1257
|
loadTypedArray,
|
|
1200
1258
|
frameState,
|
|
@@ -1204,6 +1262,7 @@ function loadAttribute(
|
|
|
1204
1262
|
loader._geometryLoaders.push(vertexBufferLoader);
|
|
1205
1263
|
const promise = vertexBufferLoader.load();
|
|
1206
1264
|
loader._loaderPromises.push(promise);
|
|
1265
|
+
|
|
1207
1266
|
// This can only execute once vertexBufferLoader.process() has run and returns true
|
|
1208
1267
|
// Save this finish callback by the loader index so it can be called
|
|
1209
1268
|
// in process().
|
|
@@ -1219,6 +1278,13 @@ function loadAttribute(
|
|
|
1219
1278
|
loadBuffer,
|
|
1220
1279
|
loadTypedArray,
|
|
1221
1280
|
);
|
|
1281
|
+
} else if (defined(spz)) {
|
|
1282
|
+
finalizeSpzAttribute(
|
|
1283
|
+
attribute,
|
|
1284
|
+
vertexBufferLoader,
|
|
1285
|
+
loadBuffer,
|
|
1286
|
+
loadTypedArray,
|
|
1287
|
+
);
|
|
1222
1288
|
} else {
|
|
1223
1289
|
finalizeAttribute(
|
|
1224
1290
|
gltf,
|
|
@@ -1240,6 +1306,7 @@ function loadVertexAttribute(
|
|
|
1240
1306
|
semanticInfo,
|
|
1241
1307
|
primitive,
|
|
1242
1308
|
draco,
|
|
1309
|
+
spz,
|
|
1243
1310
|
hasInstances,
|
|
1244
1311
|
needsPostProcessing,
|
|
1245
1312
|
frameState,
|
|
@@ -1287,6 +1354,7 @@ function loadVertexAttribute(
|
|
|
1287
1354
|
semanticInfo,
|
|
1288
1355
|
primitive,
|
|
1289
1356
|
draco,
|
|
1357
|
+
spz,
|
|
1290
1358
|
loadBuffer,
|
|
1291
1359
|
loadTypedArray,
|
|
1292
1360
|
frameState,
|
|
@@ -1360,6 +1428,7 @@ function loadInstancedAttribute(
|
|
|
1360
1428
|
semanticInfo,
|
|
1361
1429
|
undefined,
|
|
1362
1430
|
undefined,
|
|
1431
|
+
undefined,
|
|
1363
1432
|
loadBuffer,
|
|
1364
1433
|
loadTypedArray,
|
|
1365
1434
|
frameState,
|
|
@@ -1876,6 +1945,7 @@ function loadMorphTarget(
|
|
|
1876
1945
|
// Don't pass in primitive or draco object since morph targets can't be draco compressed
|
|
1877
1946
|
const primitive = undefined;
|
|
1878
1947
|
const draco = undefined;
|
|
1948
|
+
const spz = undefined;
|
|
1879
1949
|
const hasInstances = false;
|
|
1880
1950
|
|
|
1881
1951
|
for (const semantic in target) {
|
|
@@ -1896,6 +1966,7 @@ function loadMorphTarget(
|
|
|
1896
1966
|
semanticInfo,
|
|
1897
1967
|
primitive,
|
|
1898
1968
|
draco,
|
|
1969
|
+
spz,
|
|
1899
1970
|
hasInstances,
|
|
1900
1971
|
needsPostProcessing,
|
|
1901
1972
|
frameState,
|
|
@@ -1947,6 +2018,12 @@ function loadPrimitive(loader, gltfPrimitive, hasInstances, frameState) {
|
|
|
1947
2018
|
);
|
|
1948
2019
|
}
|
|
1949
2020
|
|
|
2021
|
+
const spzExtension = extensions.KHR_spz_gaussian_splats_compression;
|
|
2022
|
+
if (defined(spzExtension)) {
|
|
2023
|
+
needsPostProcessing = true;
|
|
2024
|
+
primitivePlan.needsGaussianSplats = true;
|
|
2025
|
+
}
|
|
2026
|
+
|
|
1950
2027
|
const loadForClassification = loader._loadForClassification;
|
|
1951
2028
|
const draco = extensions.KHR_draco_mesh_compression;
|
|
1952
2029
|
|
|
@@ -1979,6 +2056,7 @@ function loadPrimitive(loader, gltfPrimitive, hasInstances, frameState) {
|
|
|
1979
2056
|
semanticInfo,
|
|
1980
2057
|
gltfPrimitive,
|
|
1981
2058
|
draco,
|
|
2059
|
+
spzExtension,
|
|
1982
2060
|
hasInstances,
|
|
1983
2061
|
needsPostProcessing,
|
|
1984
2062
|
frameState,
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import Check from "../Core/Check.js";
|
|
2
|
+
import Frozen from "../Core/Frozen.js";
|
|
3
|
+
import defined from "../Core/defined.js";
|
|
4
|
+
import ResourceLoader from "./ResourceLoader.js";
|
|
5
|
+
import ResourceLoaderState from "./ResourceLoaderState.js";
|
|
6
|
+
import { loadSpz } from "@spz-loader/core";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Load a SPZ buffer from a glTF.
|
|
10
|
+
* <p>
|
|
11
|
+
* Implements the {@link ResourceLoader} interface.
|
|
12
|
+
* </p>
|
|
13
|
+
* @alias GltfSpzLoader
|
|
14
|
+
* @constructor
|
|
15
|
+
* @augments ResourceLoader
|
|
16
|
+
* @param {object} options Object with the following properties:
|
|
17
|
+
* @param {ResourceCache} options.resourceCache The {@link ResourceCache} (to avoid circular dependencies).
|
|
18
|
+
* @param {object} options.gltf The glTF JSON.
|
|
19
|
+
* @param {object} options.primitive The primitive containing the SPZ extension.
|
|
20
|
+
* @param {object} options.spz The SPZ extension object.
|
|
21
|
+
* @param {Resource} options.gltfResource The {@link Resource} containing the glTF.
|
|
22
|
+
* @param {Resource} options.baseResource The {@link Resource} that paths in the glTF JSON are relative to.
|
|
23
|
+
* @param {string} [options.cacheKey] The cache key of the resource.
|
|
24
|
+
*
|
|
25
|
+
* @private
|
|
26
|
+
*/
|
|
27
|
+
function GltfSpzLoader(options) {
|
|
28
|
+
options = options ?? Frozen.EMPTY_OBJECT;
|
|
29
|
+
const resourceCache = options.resourceCache;
|
|
30
|
+
const gltf = options.gltf;
|
|
31
|
+
const primitive = options.primitive;
|
|
32
|
+
const spz = options.spz;
|
|
33
|
+
const gltfResource = options.gltfResource;
|
|
34
|
+
const baseResource = options.baseResource;
|
|
35
|
+
const cacheKey = options.cacheKey;
|
|
36
|
+
|
|
37
|
+
//>>includeStart('debug', pragmas.debug);
|
|
38
|
+
Check.typeOf.func("options.resourceCache", resourceCache);
|
|
39
|
+
Check.typeOf.object("options.gltf", gltf);
|
|
40
|
+
Check.typeOf.object("options.primitive", primitive);
|
|
41
|
+
Check.typeOf.object("options.spz", spz);
|
|
42
|
+
Check.typeOf.object("options.gltfResource", gltfResource);
|
|
43
|
+
Check.typeOf.object("options.baseResource", baseResource);
|
|
44
|
+
//>>includeEnd('debug');
|
|
45
|
+
|
|
46
|
+
this._resourceCache = resourceCache;
|
|
47
|
+
this._gltfResource = gltfResource;
|
|
48
|
+
this._baseResource = baseResource;
|
|
49
|
+
this._gltf = gltf;
|
|
50
|
+
this._primitive = primitive;
|
|
51
|
+
this._spz = spz;
|
|
52
|
+
this._cacheKey = cacheKey;
|
|
53
|
+
this._bufferViewLoader = undefined;
|
|
54
|
+
this._bufferViewTypedArray = undefined;
|
|
55
|
+
this._decodePromise = undefined;
|
|
56
|
+
this._decodedData = undefined;
|
|
57
|
+
this._state = ResourceLoaderState.UNLOADED;
|
|
58
|
+
this._promise = undefined;
|
|
59
|
+
this._spzError = undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (defined(Object.create)) {
|
|
63
|
+
GltfSpzLoader.prototype = Object.create(ResourceLoader.prototype);
|
|
64
|
+
GltfSpzLoader.prototype.constructor = GltfSpzLoader;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
Object.defineProperties(GltfSpzLoader.prototype, {
|
|
68
|
+
/**
|
|
69
|
+
* The cache key of the resource.
|
|
70
|
+
* @memberof GltfSpzLoader.prototype
|
|
71
|
+
* @type {string}
|
|
72
|
+
* @readonly
|
|
73
|
+
* @private
|
|
74
|
+
*/
|
|
75
|
+
cacheKey: {
|
|
76
|
+
get: function () {
|
|
77
|
+
return this._cacheKey;
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
/**
|
|
81
|
+
* The decoded SPZ data.
|
|
82
|
+
* @memberof GltfSpzLoader.prototype
|
|
83
|
+
* @type {object}
|
|
84
|
+
* @readonly
|
|
85
|
+
* @private
|
|
86
|
+
*/
|
|
87
|
+
decodedData: {
|
|
88
|
+
get: function () {
|
|
89
|
+
return this._decodedData;
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
async function loadResources(loader) {
|
|
95
|
+
const resourceCache = loader._resourceCache;
|
|
96
|
+
try {
|
|
97
|
+
const bufferViewLoader = resourceCache.getBufferViewLoader({
|
|
98
|
+
gltf: loader._gltf,
|
|
99
|
+
bufferViewId: 0,
|
|
100
|
+
gltfResource: loader._gltfResource,
|
|
101
|
+
baseResource: loader._baseResource,
|
|
102
|
+
});
|
|
103
|
+
loader._bufferViewLoader = bufferViewLoader;
|
|
104
|
+
await bufferViewLoader.load();
|
|
105
|
+
|
|
106
|
+
if (loader.isDestroyed()) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
loader._bufferViewTypedArray = bufferViewLoader.typedArray;
|
|
111
|
+
loader._state = ResourceLoaderState.PROCESSING;
|
|
112
|
+
return loader;
|
|
113
|
+
} catch (error) {
|
|
114
|
+
if (loader.isDestroyed()) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
handleError(loader, error);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Loads the SPZ resource.
|
|
124
|
+
* @returns {Promise<Resource>} A promise that resolves to the resource when the SPZ is loaded.
|
|
125
|
+
* @private
|
|
126
|
+
*/
|
|
127
|
+
GltfSpzLoader.prototype.load = async function () {
|
|
128
|
+
if (defined(this._promise)) {
|
|
129
|
+
return this._promise;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
this._state = ResourceLoaderState.LOADING;
|
|
133
|
+
this._promise = loadResources(this);
|
|
134
|
+
return this._promise;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
function handleError(spzLoader, error) {
|
|
138
|
+
spzLoader.unload();
|
|
139
|
+
spzLoader._state = ResourceLoaderState.FAILED;
|
|
140
|
+
const errorMessage = "Failed to load SPZ";
|
|
141
|
+
throw spzLoader.getError(errorMessage, error);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async function processDecode(loader, decodePromise) {
|
|
145
|
+
try {
|
|
146
|
+
const gcloud = await decodePromise;
|
|
147
|
+
if (loader.isDestroyed()) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
loader.unload();
|
|
152
|
+
|
|
153
|
+
loader._decodedData = {
|
|
154
|
+
gcloud: gcloud,
|
|
155
|
+
};
|
|
156
|
+
loader._state = ResourceLoaderState.READY;
|
|
157
|
+
return loader._baseResource;
|
|
158
|
+
} catch (error) {
|
|
159
|
+
if (loader.isDestroyed()) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
loader._spzError = error;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Processes the SPZ resource.
|
|
169
|
+
* @param {FrameState} frameState The frame state.
|
|
170
|
+
* @private
|
|
171
|
+
*/
|
|
172
|
+
GltfSpzLoader.prototype.process = function (frameState) {
|
|
173
|
+
//>>includeStart('debug', pragmas.debug);
|
|
174
|
+
Check.typeOf.object("frameState", frameState);
|
|
175
|
+
//>>includeEnd('debug');
|
|
176
|
+
|
|
177
|
+
if (this._state === ResourceLoaderState.READY) {
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (this._state !== ResourceLoaderState.PROCESSING) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (defined(this._spzError)) {
|
|
186
|
+
handleError(this, this._spzError);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (!defined(this._bufferViewTypedArray)) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (defined(this._decodePromise)) {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const decodePromise = loadSpz(this._bufferViewTypedArray);
|
|
198
|
+
|
|
199
|
+
if (!defined(decodePromise)) {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
this._decodePromise = processDecode(this, decodePromise);
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Unloads the SPZ resource and frees associated resources.
|
|
208
|
+
* @private
|
|
209
|
+
*/
|
|
210
|
+
GltfSpzLoader.prototype.unload = function () {
|
|
211
|
+
if (defined(this._bufferViewLoader)) {
|
|
212
|
+
this._resourceCache.unload(this._bufferViewLoader);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
this._bufferViewLoader = undefined;
|
|
216
|
+
this._bufferViewTypedArray = undefined;
|
|
217
|
+
this._decodedData = undefined;
|
|
218
|
+
this._gltf = undefined;
|
|
219
|
+
this._primitive = undefined;
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
export default GltfSpzLoader;
|