智慧水务管理系统 - 精河县供水工程综合管理平台

GroundPolylinePrimitive.js 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  1. import ApproximateTerrainHeights from "../Core/ApproximateTerrainHeights.js";
  2. import ComponentDatatype from "../Core/ComponentDatatype.js";
  3. import Frozen from "../Core/Frozen.js";
  4. import defined from "../Core/defined.js";
  5. import destroyObject from "../Core/destroyObject.js";
  6. import DeveloperError from "../Core/DeveloperError.js";
  7. import GeometryInstance from "../Core/GeometryInstance.js";
  8. import GeometryInstanceAttribute from "../Core/GeometryInstanceAttribute.js";
  9. import GroundPolylineGeometry from "../Core/GroundPolylineGeometry.js";
  10. import DrawCommand from "../Renderer/DrawCommand.js";
  11. import Pass from "../Renderer/Pass.js";
  12. import RenderState from "../Renderer/RenderState.js";
  13. import ShaderProgram from "../Renderer/ShaderProgram.js";
  14. import ShaderSource from "../Renderer/ShaderSource.js";
  15. import PolylineShadowVolumeFS from "../Shaders/PolylineShadowVolumeFS.js";
  16. import PolylineShadowVolumeMorphFS from "../Shaders/PolylineShadowVolumeMorphFS.js";
  17. import PolylineShadowVolumeMorphVS from "../Shaders/PolylineShadowVolumeMorphVS.js";
  18. import PolylineShadowVolumeVS from "../Shaders/PolylineShadowVolumeVS.js";
  19. import BlendingState from "./BlendingState.js";
  20. import ClassificationType from "./ClassificationType.js";
  21. import CullFace from "./CullFace.js";
  22. import PolylineColorAppearance from "./PolylineColorAppearance.js";
  23. import PolylineMaterialAppearance from "./PolylineMaterialAppearance.js";
  24. import Primitive from "./Primitive.js";
  25. import SceneMode from "./SceneMode.js";
  26. import StencilConstants from "./StencilConstants.js";
  27. import StencilFunction from "./StencilFunction.js";
  28. import StencilOperation from "./StencilOperation.js";
  29. /**
  30. * A GroundPolylinePrimitive represents a polyline draped over the terrain or 3D Tiles in the {@link Scene}.
  31. * <p>
  32. * Only to be used with GeometryInstances containing {@link GroundPolylineGeometry}.
  33. * </p>
  34. *
  35. * @alias GroundPolylinePrimitive
  36. * @constructor
  37. *
  38. * @param {object} [options] Object with the following properties:
  39. * @param {Array|GeometryInstance} [options.geometryInstances] GeometryInstances containing GroundPolylineGeometry
  40. * @param {Appearance} [options.appearance] The Appearance used to render the polyline. Defaults to a white color {@link Material} on a {@link PolylineMaterialAppearance}.
  41. * @param {boolean} [options.show=true] Determines if this primitive will be shown.
  42. * @param {boolean} [options.interleave=false] When <code>true</code>, geometry vertex attributes are interleaved, which can slightly improve rendering performance but increases load time.
  43. * @param {boolean} [options.releaseGeometryInstances=true] When <code>true</code>, the primitive does not keep a reference to the input <code>geometryInstances</code> to save memory.
  44. * @param {boolean} [options.allowPicking=true] When <code>true</code>, each geometry instance will only be pickable with {@link Scene#pick}. When <code>false</code>, GPU memory is saved.
  45. * @param {boolean} [options.asynchronous=true] Determines if the primitive will be created asynchronously or block until ready. If false initializeTerrainHeights() must be called first.
  46. * @param {ClassificationType} [options.classificationType=ClassificationType.BOTH] Determines whether terrain, 3D Tiles or both will be classified.
  47. * @param {boolean} [options.debugShowBoundingVolume=false] For debugging only. Determines if this primitive's commands' bounding spheres are shown.
  48. * @param {boolean} [options.debugShowShadowVolume=false] For debugging only. Determines if the shadow volume for each geometry in the primitive is drawn. Must be <code>true</code> on creation to have effect.
  49. *
  50. * @example
  51. * // 1. Draw a polyline on terrain with a basic color material
  52. *
  53. * const instance = new Cesium.GeometryInstance({
  54. * geometry : new Cesium.GroundPolylineGeometry({
  55. * positions : Cesium.Cartesian3.fromDegreesArray([
  56. * -112.1340164450331, 36.05494287836128,
  57. * -112.08821010582645, 36.097804071380715
  58. * ]),
  59. * width : 4.0
  60. * }),
  61. * id : 'object returned when this instance is picked and to get/set per-instance attributes'
  62. * });
  63. *
  64. * scene.groundPrimitives.add(new Cesium.GroundPolylinePrimitive({
  65. * geometryInstances : instance,
  66. * appearance : new Cesium.PolylineMaterialAppearance()
  67. * }));
  68. *
  69. * // 2. Draw a looped polyline on terrain with per-instance color and a distance display condition.
  70. * // Distance display conditions for polylines on terrain are based on an approximate terrain height
  71. * // instead of true terrain height.
  72. *
  73. * const instance2 = new Cesium.GeometryInstance({
  74. * geometry : new Cesium.GroundPolylineGeometry({
  75. * positions : Cesium.Cartesian3.fromDegreesArray([
  76. * -112.1340164450331, 36.05494287836128,
  77. * -112.08821010582645, 36.097804071380715,
  78. * -112.13296079730024, 36.168769146801104
  79. * ]),
  80. * loop : true,
  81. * width : 4.0
  82. * }),
  83. * attributes : {
  84. * color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.fromCssColorString('green').withAlpha(0.7)),
  85. * distanceDisplayCondition : new Cesium.DistanceDisplayConditionGeometryInstanceAttribute(1000, 30000)
  86. * },
  87. * id : 'object returned when this instance is picked and to get/set per-instance attributes'
  88. * });
  89. *
  90. * scene.groundPrimitives.add(new Cesium.GroundPolylinePrimitive({
  91. * geometryInstances : instance2,
  92. * appearance : new Cesium.PolylineColorAppearance()
  93. * }));
  94. */
  95. function GroundPolylinePrimitive(options) {
  96. options = options ?? Frozen.EMPTY_OBJECT;
  97. /**
  98. * The geometry instances rendered with this primitive. This may
  99. * be <code>undefined</code> if <code>options.releaseGeometryInstances</code>
  100. * is <code>true</code> when the primitive is constructed.
  101. * <p>
  102. * Changing this property after the primitive is rendered has no effect.
  103. * </p>
  104. *
  105. * @readonly
  106. * @type {Array|GeometryInstance}
  107. *
  108. * @default undefined
  109. */
  110. this.geometryInstances = options.geometryInstances;
  111. this._hasPerInstanceColors = true;
  112. let appearance = options.appearance;
  113. if (!defined(appearance)) {
  114. appearance = new PolylineMaterialAppearance();
  115. }
  116. /**
  117. * The {@link Appearance} used to shade this primitive. Each geometry
  118. * instance is shaded with the same appearance. Some appearances, like
  119. * {@link PolylineColorAppearance} allow giving each instance unique
  120. * properties.
  121. *
  122. * @type Appearance
  123. *
  124. * @default undefined
  125. */
  126. this.appearance = appearance;
  127. /**
  128. * Determines if the primitive will be shown. This affects all geometry
  129. * instances in the primitive.
  130. *
  131. * @type {boolean}
  132. *
  133. * @default true
  134. */
  135. this.show = options.show ?? true;
  136. /**
  137. * Determines whether terrain, 3D Tiles or both will be classified.
  138. *
  139. * @type {ClassificationType}
  140. *
  141. * @default ClassificationType.BOTH
  142. */
  143. this.classificationType =
  144. options.classificationType ?? ClassificationType.BOTH;
  145. /**
  146. * This property is for debugging only; it is not for production use nor is it optimized.
  147. * <p>
  148. * Draws the bounding sphere for each draw command in the primitive.
  149. * </p>
  150. *
  151. * @type {boolean}
  152. *
  153. * @default false
  154. */
  155. this.debugShowBoundingVolume = options.debugShowBoundingVolume ?? false;
  156. // Shadow volume is shown by removing a discard in the shader, so this isn't toggleable.
  157. this._debugShowShadowVolume = options.debugShowShadowVolume ?? false;
  158. this._primitiveOptions = {
  159. geometryInstances: undefined,
  160. appearance: undefined,
  161. vertexCacheOptimize: false,
  162. interleave: options.interleave ?? false,
  163. releaseGeometryInstances: options.releaseGeometryInstances ?? true,
  164. allowPicking: options.allowPicking ?? true,
  165. asynchronous: options.asynchronous ?? true,
  166. compressVertices: false,
  167. _createShaderProgramFunction: undefined,
  168. _createCommandsFunction: undefined,
  169. _updateAndQueueCommandsFunction: undefined,
  170. };
  171. // Used when inserting in an OrderedPrimitiveCollection
  172. this._zIndex = undefined;
  173. this._ready = false;
  174. this._primitive = undefined;
  175. this._sp = undefined;
  176. this._sp2D = undefined;
  177. this._spMorph = undefined;
  178. this._renderState = getRenderState(false);
  179. this._renderState3DTiles = getRenderState(true);
  180. this._renderStateMorph = RenderState.fromCache({
  181. cull: {
  182. enabled: true,
  183. face: CullFace.FRONT, // Geometry is "inverted," so cull front when materials on volume instead of on terrain (morph)
  184. },
  185. depthTest: {
  186. enabled: true,
  187. },
  188. blending: BlendingState.PRE_MULTIPLIED_ALPHA_BLEND,
  189. depthMask: false,
  190. });
  191. }
  192. Object.defineProperties(GroundPolylinePrimitive.prototype, {
  193. /**
  194. * Determines if geometry vertex attributes are interleaved, which can slightly improve rendering performance.
  195. *
  196. * @memberof GroundPolylinePrimitive.prototype
  197. *
  198. * @type {boolean}
  199. * @readonly
  200. *
  201. * @default false
  202. */
  203. interleave: {
  204. get: function () {
  205. return this._primitiveOptions.interleave;
  206. },
  207. },
  208. /**
  209. * When <code>true</code>, the primitive does not keep a reference to the input <code>geometryInstances</code> to save memory.
  210. *
  211. * @memberof GroundPolylinePrimitive.prototype
  212. *
  213. * @type {boolean}
  214. * @readonly
  215. *
  216. * @default true
  217. */
  218. releaseGeometryInstances: {
  219. get: function () {
  220. return this._primitiveOptions.releaseGeometryInstances;
  221. },
  222. },
  223. /**
  224. * When <code>true</code>, each geometry instance will only be pickable with {@link Scene#pick}. When <code>false</code>, GPU memory is saved.
  225. *
  226. * @memberof GroundPolylinePrimitive.prototype
  227. *
  228. * @type {boolean}
  229. * @readonly
  230. *
  231. * @default true
  232. */
  233. allowPicking: {
  234. get: function () {
  235. return this._primitiveOptions.allowPicking;
  236. },
  237. },
  238. /**
  239. * Determines if the geometry instances will be created and batched on a web worker.
  240. *
  241. * @memberof GroundPolylinePrimitive.prototype
  242. *
  243. * @type {boolean}
  244. * @readonly
  245. *
  246. * @default true
  247. */
  248. asynchronous: {
  249. get: function () {
  250. return this._primitiveOptions.asynchronous;
  251. },
  252. },
  253. /**
  254. * Determines if the primitive is complete and ready to render. If this property is
  255. * true, the primitive will be rendered the next time that {@link GroundPolylinePrimitive#update}
  256. * is called.
  257. *
  258. * @memberof GroundPolylinePrimitive.prototype
  259. *
  260. * @type {boolean}
  261. * @readonly
  262. */
  263. ready: {
  264. get: function () {
  265. return this._ready;
  266. },
  267. },
  268. /**
  269. * This property is for debugging only; it is not for production use nor is it optimized.
  270. * <p>
  271. * If true, draws the shadow volume for each geometry in the primitive.
  272. * </p>
  273. *
  274. * @memberof GroundPolylinePrimitive.prototype
  275. *
  276. * @type {boolean}
  277. * @readonly
  278. *
  279. * @default false
  280. */
  281. debugShowShadowVolume: {
  282. get: function () {
  283. return this._debugShowShadowVolume;
  284. },
  285. },
  286. });
  287. /**
  288. * Initializes the minimum and maximum terrain heights. This only needs to be called if you are creating the
  289. * GroundPolylinePrimitive synchronously.
  290. *
  291. * @returns {Promise<void>} A promise that will resolve once the terrain heights have been loaded.
  292. */
  293. GroundPolylinePrimitive.initializeTerrainHeights = function () {
  294. return ApproximateTerrainHeights.initialize();
  295. };
  296. function createShaderProgram(groundPolylinePrimitive, frameState, appearance) {
  297. const context = frameState.context;
  298. const primitive = groundPolylinePrimitive._primitive;
  299. const attributeLocations = primitive._attributeLocations;
  300. let vs = primitive._batchTable.getVertexShaderCallback()(
  301. PolylineShadowVolumeVS,
  302. );
  303. vs = Primitive._appendShowToShader(primitive, vs);
  304. vs = Primitive._appendDistanceDisplayConditionToShader(primitive, vs);
  305. vs = Primitive._modifyShaderPosition(
  306. groundPolylinePrimitive,
  307. vs,
  308. frameState.scene3DOnly,
  309. );
  310. let vsMorph = primitive._batchTable.getVertexShaderCallback()(
  311. PolylineShadowVolumeMorphVS,
  312. );
  313. vsMorph = Primitive._appendShowToShader(primitive, vsMorph);
  314. vsMorph = Primitive._appendDistanceDisplayConditionToShader(
  315. primitive,
  316. vsMorph,
  317. );
  318. vsMorph = Primitive._modifyShaderPosition(
  319. groundPolylinePrimitive,
  320. vsMorph,
  321. frameState.scene3DOnly,
  322. );
  323. // Access pick color from fragment shader.
  324. // Helps with varying budget.
  325. let fs = primitive._batchTable.getVertexShaderCallback()(
  326. PolylineShadowVolumeFS,
  327. );
  328. const vsDefines = [
  329. `GLOBE_MINIMUM_ALTITUDE ${frameState.mapProjection.ellipsoid.minimumRadius.toFixed(
  330. 1,
  331. )}`,
  332. ];
  333. let colorDefine = "";
  334. let materialShaderSource = "";
  335. if (defined(appearance.material)) {
  336. materialShaderSource = defined(appearance.material)
  337. ? appearance.material.shaderSource
  338. : "";
  339. // Check for use of v_width and v_polylineAngle in material shader
  340. // to determine whether these varyings should be active in the vertex shader.
  341. if (materialShaderSource.search(/in\s+float\s+v_polylineAngle;/g) !== -1) {
  342. vsDefines.push("ANGLE_VARYING");
  343. }
  344. if (materialShaderSource.search(/in\s+float\s+v_width;/g) !== -1) {
  345. vsDefines.push("WIDTH_VARYING");
  346. }
  347. } else {
  348. colorDefine = "PER_INSTANCE_COLOR";
  349. }
  350. vsDefines.push(colorDefine);
  351. const fsDefines = groundPolylinePrimitive.debugShowShadowVolume
  352. ? ["DEBUG_SHOW_VOLUME", colorDefine]
  353. : [colorDefine];
  354. const vsColor3D = new ShaderSource({
  355. defines: vsDefines,
  356. sources: [vs],
  357. });
  358. const fsColor3D = new ShaderSource({
  359. defines: fsDefines,
  360. sources: [materialShaderSource, fs],
  361. });
  362. groundPolylinePrimitive._sp = ShaderProgram.replaceCache({
  363. context: context,
  364. shaderProgram: primitive._sp,
  365. vertexShaderSource: vsColor3D,
  366. fragmentShaderSource: fsColor3D,
  367. attributeLocations: attributeLocations,
  368. });
  369. // Derive 2D/CV
  370. let colorProgram2D = context.shaderCache.getDerivedShaderProgram(
  371. groundPolylinePrimitive._sp,
  372. "2dColor",
  373. );
  374. if (!defined(colorProgram2D)) {
  375. const vsColor2D = new ShaderSource({
  376. defines: vsDefines.concat(["COLUMBUS_VIEW_2D"]),
  377. sources: [vs],
  378. });
  379. colorProgram2D = context.shaderCache.createDerivedShaderProgram(
  380. groundPolylinePrimitive._sp,
  381. "2dColor",
  382. {
  383. context: context,
  384. shaderProgram: groundPolylinePrimitive._sp2D,
  385. vertexShaderSource: vsColor2D,
  386. fragmentShaderSource: fsColor3D,
  387. attributeLocations: attributeLocations,
  388. },
  389. );
  390. }
  391. groundPolylinePrimitive._sp2D = colorProgram2D;
  392. // Derive Morph
  393. let colorProgramMorph = context.shaderCache.getDerivedShaderProgram(
  394. groundPolylinePrimitive._sp,
  395. "MorphColor",
  396. );
  397. if (!defined(colorProgramMorph)) {
  398. const vsColorMorph = new ShaderSource({
  399. defines: vsDefines.concat([
  400. `MAX_TERRAIN_HEIGHT ${ApproximateTerrainHeights._defaultMaxTerrainHeight.toFixed(
  401. 1,
  402. )}`,
  403. ]),
  404. sources: [vsMorph],
  405. });
  406. fs = primitive._batchTable.getVertexShaderCallback()(
  407. PolylineShadowVolumeMorphFS,
  408. );
  409. const fsColorMorph = new ShaderSource({
  410. defines: fsDefines,
  411. sources: [materialShaderSource, fs],
  412. });
  413. colorProgramMorph = context.shaderCache.createDerivedShaderProgram(
  414. groundPolylinePrimitive._sp,
  415. "MorphColor",
  416. {
  417. context: context,
  418. shaderProgram: groundPolylinePrimitive._spMorph,
  419. vertexShaderSource: vsColorMorph,
  420. fragmentShaderSource: fsColorMorph,
  421. attributeLocations: attributeLocations,
  422. },
  423. );
  424. }
  425. groundPolylinePrimitive._spMorph = colorProgramMorph;
  426. }
  427. function getRenderState(mask3DTiles) {
  428. return RenderState.fromCache({
  429. cull: {
  430. enabled: true, // prevent double-draw. Geometry is "inverted" (reversed winding order) so we're drawing backfaces.
  431. },
  432. blending: BlendingState.PRE_MULTIPLIED_ALPHA_BLEND,
  433. depthMask: false,
  434. stencilTest: {
  435. enabled: mask3DTiles,
  436. frontFunction: StencilFunction.EQUAL,
  437. frontOperation: {
  438. fail: StencilOperation.KEEP,
  439. zFail: StencilOperation.KEEP,
  440. zPass: StencilOperation.KEEP,
  441. },
  442. backFunction: StencilFunction.EQUAL,
  443. backOperation: {
  444. fail: StencilOperation.KEEP,
  445. zFail: StencilOperation.KEEP,
  446. zPass: StencilOperation.KEEP,
  447. },
  448. reference: StencilConstants.CESIUM_3D_TILE_MASK,
  449. mask: StencilConstants.CESIUM_3D_TILE_MASK,
  450. },
  451. });
  452. }
  453. function createCommands(
  454. groundPolylinePrimitive,
  455. appearance,
  456. material,
  457. translucent,
  458. colorCommands,
  459. pickCommands,
  460. ) {
  461. const primitive = groundPolylinePrimitive._primitive;
  462. const length = primitive._va.length;
  463. colorCommands.length = length;
  464. pickCommands.length = length;
  465. const isPolylineColorAppearance =
  466. appearance instanceof PolylineColorAppearance;
  467. const materialUniforms = isPolylineColorAppearance ? {} : material._uniforms;
  468. const uniformMap =
  469. primitive._batchTable.getUniformMapCallback()(materialUniforms);
  470. for (let i = 0; i < length; i++) {
  471. const vertexArray = primitive._va[i];
  472. let command = colorCommands[i];
  473. if (!defined(command)) {
  474. command = colorCommands[i] = new DrawCommand({
  475. owner: groundPolylinePrimitive,
  476. primitiveType: primitive._primitiveType,
  477. });
  478. }
  479. command.vertexArray = vertexArray;
  480. command.renderState = groundPolylinePrimitive._renderState;
  481. command.shaderProgram = groundPolylinePrimitive._sp;
  482. command.uniformMap = uniformMap;
  483. command.pass = Pass.TERRAIN_CLASSIFICATION;
  484. command.pickId = "czm_batchTable_pickColor(v_endPlaneNormalEcAndBatchId.w)";
  485. const derivedTilesetCommand = DrawCommand.shallowClone(
  486. command,
  487. command.derivedCommands.tileset,
  488. );
  489. derivedTilesetCommand.renderState =
  490. groundPolylinePrimitive._renderState3DTiles;
  491. derivedTilesetCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;
  492. command.derivedCommands.tileset = derivedTilesetCommand;
  493. // derive for 2D
  494. const derived2DCommand = DrawCommand.shallowClone(
  495. command,
  496. command.derivedCommands.color2D,
  497. );
  498. derived2DCommand.shaderProgram = groundPolylinePrimitive._sp2D;
  499. command.derivedCommands.color2D = derived2DCommand;
  500. const derived2DTilesetCommand = DrawCommand.shallowClone(
  501. derivedTilesetCommand,
  502. derivedTilesetCommand.derivedCommands.color2D,
  503. );
  504. derived2DTilesetCommand.shaderProgram = groundPolylinePrimitive._sp2D;
  505. derivedTilesetCommand.derivedCommands.color2D = derived2DTilesetCommand;
  506. // derive for Morph
  507. const derivedMorphCommand = DrawCommand.shallowClone(
  508. command,
  509. command.derivedCommands.colorMorph,
  510. );
  511. derivedMorphCommand.renderState = groundPolylinePrimitive._renderStateMorph;
  512. derivedMorphCommand.shaderProgram = groundPolylinePrimitive._spMorph;
  513. derivedMorphCommand.pickId = "czm_batchTable_pickColor(v_batchId)";
  514. command.derivedCommands.colorMorph = derivedMorphCommand;
  515. }
  516. }
  517. function updateAndQueueCommand(
  518. groundPolylinePrimitive,
  519. command,
  520. frameState,
  521. modelMatrix,
  522. cull,
  523. boundingVolume,
  524. debugShowBoundingVolume,
  525. ) {
  526. // Use derived appearance command for morph and 2D
  527. if (frameState.mode === SceneMode.MORPHING) {
  528. command = command.derivedCommands.colorMorph;
  529. } else if (frameState.mode !== SceneMode.SCENE3D) {
  530. command = command.derivedCommands.color2D;
  531. }
  532. command.modelMatrix = modelMatrix;
  533. command.boundingVolume = boundingVolume;
  534. command.cull = cull;
  535. command.debugShowBoundingVolume = debugShowBoundingVolume;
  536. frameState.commandList.push(command);
  537. }
  538. function updateAndQueueCommands(
  539. groundPolylinePrimitive,
  540. frameState,
  541. colorCommands,
  542. pickCommands,
  543. modelMatrix,
  544. cull,
  545. debugShowBoundingVolume,
  546. ) {
  547. const primitive = groundPolylinePrimitive._primitive;
  548. Primitive._updateBoundingVolumes(primitive, frameState, modelMatrix); // Expected to be identity - GroundPrimitives don't support other model matrices
  549. let boundingSpheres;
  550. if (frameState.mode === SceneMode.SCENE3D) {
  551. boundingSpheres = primitive._boundingSphereWC;
  552. } else if (frameState.mode === SceneMode.COLUMBUS_VIEW) {
  553. boundingSpheres = primitive._boundingSphereCV;
  554. } else if (
  555. frameState.mode === SceneMode.SCENE2D &&
  556. defined(primitive._boundingSphere2D)
  557. ) {
  558. boundingSpheres = primitive._boundingSphere2D;
  559. } else if (defined(primitive._boundingSphereMorph)) {
  560. boundingSpheres = primitive._boundingSphereMorph;
  561. }
  562. const morphing = frameState.mode === SceneMode.MORPHING;
  563. const classificationType = groundPolylinePrimitive.classificationType;
  564. const queueTerrainCommands =
  565. classificationType !== ClassificationType.CESIUM_3D_TILE;
  566. const queue3DTilesCommands =
  567. classificationType !== ClassificationType.TERRAIN && !morphing;
  568. let command;
  569. const passes = frameState.passes;
  570. if (passes.render || (passes.pick && primitive.allowPicking)) {
  571. const colorLength = colorCommands.length;
  572. for (let j = 0; j < colorLength; ++j) {
  573. const boundingVolume = boundingSpheres[j];
  574. if (queueTerrainCommands) {
  575. command = colorCommands[j];
  576. updateAndQueueCommand(
  577. groundPolylinePrimitive,
  578. command,
  579. frameState,
  580. modelMatrix,
  581. cull,
  582. boundingVolume,
  583. debugShowBoundingVolume,
  584. );
  585. }
  586. if (queue3DTilesCommands) {
  587. command = colorCommands[j].derivedCommands.tileset;
  588. updateAndQueueCommand(
  589. groundPolylinePrimitive,
  590. command,
  591. frameState,
  592. modelMatrix,
  593. cull,
  594. boundingVolume,
  595. debugShowBoundingVolume,
  596. );
  597. }
  598. }
  599. }
  600. }
  601. /**
  602. * Called when {@link Viewer} or {@link CesiumWidget} render the scene to
  603. * get the draw commands needed to render this primitive.
  604. * <p>
  605. * Do not call this function directly. This is documented just to
  606. * list the exceptions that may be propagated when the scene is rendered:
  607. * </p>
  608. *
  609. * @exception {DeveloperError} For synchronous GroundPolylinePrimitives, you must call GroundPolylinePrimitives.initializeTerrainHeights() and wait for the returned promise to resolve.
  610. * @exception {DeveloperError} All GeometryInstances must have color attributes to use PolylineColorAppearance with GroundPolylinePrimitive.
  611. */
  612. GroundPolylinePrimitive.prototype.update = function (frameState) {
  613. if (!defined(this._primitive) && !defined(this.geometryInstances)) {
  614. return;
  615. }
  616. if (!ApproximateTerrainHeights.initialized) {
  617. //>>includeStart('debug', pragmas.debug);
  618. if (!this.asynchronous) {
  619. throw new DeveloperError(
  620. "For synchronous GroundPolylinePrimitives, you must call GroundPolylinePrimitives.initializeTerrainHeights() and wait for the returned promise to resolve.",
  621. );
  622. }
  623. //>>includeEnd('debug');
  624. GroundPolylinePrimitive.initializeTerrainHeights();
  625. return;
  626. }
  627. let i;
  628. const that = this;
  629. const primitiveOptions = this._primitiveOptions;
  630. if (!defined(this._primitive)) {
  631. const geometryInstances = Array.isArray(this.geometryInstances)
  632. ? this.geometryInstances
  633. : [this.geometryInstances];
  634. const geometryInstancesLength = geometryInstances.length;
  635. const groundInstances = new Array(geometryInstancesLength);
  636. let attributes;
  637. // Check if each instance has a color attribute.
  638. for (i = 0; i < geometryInstancesLength; ++i) {
  639. attributes = geometryInstances[i].attributes;
  640. if (!defined(attributes) || !defined(attributes.color)) {
  641. this._hasPerInstanceColors = false;
  642. break;
  643. }
  644. }
  645. for (i = 0; i < geometryInstancesLength; ++i) {
  646. const geometryInstance = geometryInstances[i];
  647. attributes = {};
  648. const instanceAttributes = geometryInstance.attributes;
  649. for (const attributeKey in instanceAttributes) {
  650. if (instanceAttributes.hasOwnProperty(attributeKey)) {
  651. attributes[attributeKey] = instanceAttributes[attributeKey];
  652. }
  653. }
  654. // Automatically create line width attribute if not already given
  655. if (!defined(attributes.width)) {
  656. attributes.width = new GeometryInstanceAttribute({
  657. componentDatatype: ComponentDatatype.UNSIGNED_BYTE,
  658. componentsPerAttribute: 1.0,
  659. value: [geometryInstance.geometry.width],
  660. });
  661. }
  662. // Update each geometry for framestate.scene3DOnly = true and projection
  663. geometryInstance.geometry._scene3DOnly = frameState.scene3DOnly;
  664. GroundPolylineGeometry.setProjectionAndEllipsoid(
  665. geometryInstance.geometry,
  666. frameState.mapProjection,
  667. );
  668. groundInstances[i] = new GeometryInstance({
  669. geometry: geometryInstance.geometry,
  670. attributes: attributes,
  671. id: geometryInstance.id,
  672. pickPrimitive: that,
  673. });
  674. }
  675. primitiveOptions.geometryInstances = groundInstances;
  676. primitiveOptions.appearance = this.appearance;
  677. primitiveOptions._createShaderProgramFunction = function (
  678. primitive,
  679. frameState,
  680. appearance,
  681. ) {
  682. createShaderProgram(that, frameState, appearance);
  683. };
  684. primitiveOptions._createCommandsFunction = function (
  685. primitive,
  686. appearance,
  687. material,
  688. translucent,
  689. twoPasses,
  690. colorCommands,
  691. pickCommands,
  692. ) {
  693. createCommands(
  694. that,
  695. appearance,
  696. material,
  697. translucent,
  698. colorCommands,
  699. pickCommands,
  700. );
  701. };
  702. primitiveOptions._updateAndQueueCommandsFunction = function (
  703. primitive,
  704. frameState,
  705. colorCommands,
  706. pickCommands,
  707. modelMatrix,
  708. cull,
  709. debugShowBoundingVolume,
  710. twoPasses,
  711. ) {
  712. updateAndQueueCommands(
  713. that,
  714. frameState,
  715. colorCommands,
  716. pickCommands,
  717. modelMatrix,
  718. cull,
  719. debugShowBoundingVolume,
  720. );
  721. };
  722. this._primitive = new Primitive(primitiveOptions);
  723. }
  724. if (
  725. this.appearance instanceof PolylineColorAppearance &&
  726. !this._hasPerInstanceColors
  727. ) {
  728. throw new DeveloperError(
  729. "All GeometryInstances must have color attributes to use PolylineColorAppearance with GroundPolylinePrimitive.",
  730. );
  731. }
  732. this._primitive.appearance = this.appearance;
  733. this._primitive.show = this.show;
  734. this._primitive.debugShowBoundingVolume = this.debugShowBoundingVolume;
  735. this._primitive.update(frameState);
  736. frameState.afterRender.push(() => {
  737. if (!this._ready && defined(this._primitive) && this._primitive.ready) {
  738. this._ready = true;
  739. if (this.releaseGeometryInstances) {
  740. this.geometryInstances = undefined;
  741. }
  742. }
  743. });
  744. };
  745. /**
  746. * Returns the modifiable per-instance attributes for a {@link GeometryInstance}.
  747. *
  748. * @param {*} id The id of the {@link GeometryInstance}.
  749. * @returns {object} The typed array in the attribute's format or undefined if the is no instance with id.
  750. *
  751. * @exception {DeveloperError} must call update before calling getGeometryInstanceAttributes.
  752. *
  753. * @example
  754. * const attributes = primitive.getGeometryInstanceAttributes('an id');
  755. * attributes.color = Cesium.ColorGeometryInstanceAttribute.toValue(Cesium.Color.AQUA);
  756. * attributes.show = Cesium.ShowGeometryInstanceAttribute.toValue(true);
  757. */
  758. GroundPolylinePrimitive.prototype.getGeometryInstanceAttributes = function (
  759. id,
  760. ) {
  761. //>>includeStart('debug', pragmas.debug);
  762. if (!defined(this._primitive)) {
  763. throw new DeveloperError(
  764. "must call update before calling getGeometryInstanceAttributes",
  765. );
  766. }
  767. //>>includeEnd('debug');
  768. return this._primitive.getGeometryInstanceAttributes(id);
  769. };
  770. /**
  771. * Checks if the given Scene supports GroundPolylinePrimitives.
  772. * GroundPolylinePrimitives require support for the WEBGL_depth_texture extension.
  773. *
  774. * @param {Scene} scene The current scene.
  775. * @returns {boolean} Whether or not the current scene supports GroundPolylinePrimitives.
  776. */
  777. GroundPolylinePrimitive.isSupported = function (scene) {
  778. return scene.frameState.context.depthTexture;
  779. };
  780. /**
  781. * Returns true if this object was destroyed; otherwise, false.
  782. * <p>
  783. * If this object was destroyed, it should not be used; calling any function other than
  784. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
  785. * </p>
  786. *
  787. * @returns {boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>.
  788. *
  789. * @see GroundPolylinePrimitive#destroy
  790. */
  791. GroundPolylinePrimitive.prototype.isDestroyed = function () {
  792. return false;
  793. };
  794. /**
  795. * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
  796. * release of WebGL resources, instead of relying on the garbage collector to destroy this object.
  797. * <p>
  798. * Once an object is destroyed, it should not be used; calling any function other than
  799. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
  800. * assign the return value (<code>undefined</code>) to the object as done in the example.
  801. * </p>
  802. *
  803. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  804. *
  805. * @example
  806. * e = e && e.destroy();
  807. *
  808. * @see GroundPolylinePrimitive#isDestroyed
  809. */
  810. GroundPolylinePrimitive.prototype.destroy = function () {
  811. this._primitive = this._primitive && this._primitive.destroy();
  812. this._sp = this._sp && this._sp.destroy();
  813. // Derived programs, destroyed above if they existed.
  814. this._sp2D = undefined;
  815. this._spMorph = undefined;
  816. return destroyObject(this);
  817. };
  818. export default GroundPolylinePrimitive;