Cesium3DTilesInspector.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. import { Check, destroyObject, getElement } from "@cesium/engine";
  2. import knockout from "../ThirdParty/knockout.js";
  3. import InspectorShared from "../InspectorShared.js";
  4. import Cesium3DTilesInspectorViewModel from "./Cesium3DTilesInspectorViewModel.js";
  5. /**
  6. * Inspector widget to aid in debugging 3D Tiles
  7. *
  8. * @alias Cesium3DTilesInspector
  9. * @constructor
  10. *
  11. * @param {Element|string} container The DOM element or ID that will contain the widget.
  12. * @param {Scene} scene the Scene instance to use.
  13. */
  14. function Cesium3DTilesInspector(container, scene) {
  15. //>>includeStart('debug', pragmas.debug);
  16. Check.defined("container", container);
  17. Check.typeOf.object("scene", scene);
  18. //>>includeEnd('debug');
  19. container = getElement(container);
  20. const element = document.createElement("div");
  21. const performanceContainer = document.createElement("div");
  22. performanceContainer.setAttribute("data-bind", "visible: performance");
  23. const viewModel = new Cesium3DTilesInspectorViewModel(
  24. scene,
  25. performanceContainer
  26. );
  27. this._viewModel = viewModel;
  28. this._container = container;
  29. this._element = element;
  30. const text = document.createElement("div");
  31. text.textContent = "3D Tiles Inspector";
  32. text.className = "cesium-cesiumInspector-button";
  33. text.setAttribute("data-bind", "click: toggleInspector");
  34. element.appendChild(text);
  35. element.className = "cesium-cesiumInspector cesium-3DTilesInspector";
  36. element.setAttribute(
  37. "data-bind",
  38. 'css: { "cesium-cesiumInspector-visible" : inspectorVisible, "cesium-cesiumInspector-hidden" : !inspectorVisible}'
  39. );
  40. container.appendChild(element);
  41. const panel = document.createElement("div");
  42. panel.className = "cesium-cesiumInspector-dropDown";
  43. element.appendChild(panel);
  44. const createSection = InspectorShared.createSection;
  45. const createCheckbox = InspectorShared.createCheckbox;
  46. const createRangeInput = InspectorShared.createRangeInput;
  47. const createButton = InspectorShared.createButton;
  48. const tilesetPanelContents = createSection(
  49. panel,
  50. "Tileset",
  51. "tilesetVisible",
  52. "toggleTileset"
  53. );
  54. const displayPanelContents = createSection(
  55. panel,
  56. "Display",
  57. "displayVisible",
  58. "toggleDisplay"
  59. );
  60. const updatePanelContents = createSection(
  61. panel,
  62. "Update",
  63. "updateVisible",
  64. "toggleUpdate"
  65. );
  66. const loggingPanelContents = createSection(
  67. panel,
  68. "Logging",
  69. "loggingVisible",
  70. "toggleLogging"
  71. );
  72. const tileDebugLabelsPanelContents = createSection(
  73. panel,
  74. "Tile Debug Labels",
  75. "tileDebugLabelsVisible",
  76. "toggleTileDebugLabels"
  77. );
  78. const stylePanelContents = createSection(
  79. panel,
  80. "Style",
  81. "styleVisible",
  82. "toggleStyle"
  83. );
  84. const optimizationPanelContents = createSection(
  85. panel,
  86. "Optimization",
  87. "optimizationVisible",
  88. "toggleOptimization"
  89. );
  90. const properties = document.createElement("div");
  91. properties.className = "field-group";
  92. const propertiesLabel = document.createElement("label");
  93. propertiesLabel.className = "field-label";
  94. propertiesLabel.appendChild(document.createTextNode("Properties: "));
  95. const propertiesField = document.createElement("div");
  96. propertiesField.setAttribute("data-bind", "text: properties");
  97. properties.appendChild(propertiesLabel);
  98. properties.appendChild(propertiesField);
  99. tilesetPanelContents.appendChild(properties);
  100. tilesetPanelContents.appendChild(
  101. createButton("Pick Tileset", "togglePickTileset", "pickActive")
  102. );
  103. tilesetPanelContents.appendChild(
  104. createButton("Trim Tiles Cache", "trimTilesCache")
  105. );
  106. tilesetPanelContents.appendChild(createCheckbox("Enable Picking", "picking"));
  107. displayPanelContents.appendChild(createCheckbox("Colorize", "colorize"));
  108. const wireframeCheckbox = displayPanelContents.appendChild(
  109. createCheckbox(
  110. "Wireframe",
  111. "wireframe",
  112. "_tileset === undefined || hasEnabledWireframe"
  113. )
  114. );
  115. // Create warning text when the Wireframe checkbox is disabled
  116. const warningText = document.createElement("p");
  117. warningText.setAttribute(
  118. "data-bind",
  119. "visible: _tileset !== undefined && !hasEnabledWireframe"
  120. );
  121. warningText.setAttribute(
  122. "class",
  123. "cesium-3DTilesInspector-disabledElementsInfo"
  124. );
  125. warningText.innerText =
  126. "Set enableDebugWireframe to true in the tileset constructor to enable this option.";
  127. wireframeCheckbox.appendChild(warningText);
  128. displayPanelContents.appendChild(
  129. createCheckbox("Bounding Volumes", "showBoundingVolumes")
  130. );
  131. displayPanelContents.appendChild(
  132. createCheckbox("Content Volumes", "showContentBoundingVolumes")
  133. );
  134. displayPanelContents.appendChild(
  135. createCheckbox("Request Volumes", "showRequestVolumes")
  136. );
  137. displayPanelContents.appendChild(
  138. createCheckbox("Point Cloud Shading", "pointCloudShading")
  139. );
  140. const pointCloudShadingContainer = document.createElement("div");
  141. pointCloudShadingContainer.setAttribute(
  142. "data-bind",
  143. "visible: pointCloudShading"
  144. );
  145. pointCloudShadingContainer.appendChild(
  146. createRangeInput("Geometric Error Scale", "geometricErrorScale", 0, 2, 0.01)
  147. );
  148. pointCloudShadingContainer.appendChild(
  149. createRangeInput("Maximum Attenuation", "maximumAttenuation", 0, 32, 1)
  150. );
  151. pointCloudShadingContainer.appendChild(
  152. createRangeInput("Base Resolution", "baseResolution", 0, 1, 0.01)
  153. );
  154. pointCloudShadingContainer.appendChild(
  155. createCheckbox("Eye Dome Lighting (EDL)", "eyeDomeLighting")
  156. );
  157. displayPanelContents.appendChild(pointCloudShadingContainer);
  158. const edlContainer = document.createElement("div");
  159. edlContainer.setAttribute("data-bind", "visible: eyeDomeLighting");
  160. edlContainer.appendChild(
  161. createRangeInput("EDL Strength", "eyeDomeLightingStrength", 0, 2.0, 0.1)
  162. );
  163. edlContainer.appendChild(
  164. createRangeInput("EDL Radius", "eyeDomeLightingRadius", 0, 4.0, 0.1)
  165. );
  166. pointCloudShadingContainer.appendChild(edlContainer);
  167. updatePanelContents.appendChild(
  168. createCheckbox("Freeze Frame", "freezeFrame")
  169. );
  170. updatePanelContents.appendChild(
  171. createCheckbox("Dynamic Screen Space Error", "dynamicScreenSpaceError")
  172. );
  173. const sseContainer = document.createElement("div");
  174. sseContainer.appendChild(
  175. createRangeInput(
  176. "Maximum Screen Space Error",
  177. "maximumScreenSpaceError",
  178. 0,
  179. 128,
  180. 1
  181. )
  182. );
  183. updatePanelContents.appendChild(sseContainer);
  184. const dynamicScreenSpaceErrorContainer = document.createElement("div");
  185. dynamicScreenSpaceErrorContainer.setAttribute(
  186. "data-bind",
  187. "visible: dynamicScreenSpaceError"
  188. );
  189. dynamicScreenSpaceErrorContainer.appendChild(
  190. createRangeInput(
  191. "Screen Space Error Density",
  192. "dynamicScreenSpaceErrorDensitySliderValue",
  193. 0,
  194. 1,
  195. 0.005,
  196. "dynamicScreenSpaceErrorDensity"
  197. )
  198. );
  199. dynamicScreenSpaceErrorContainer.appendChild(
  200. createRangeInput(
  201. "Screen Space Error Factor",
  202. "dynamicScreenSpaceErrorFactor",
  203. 1,
  204. 10,
  205. 0.1
  206. )
  207. );
  208. updatePanelContents.appendChild(dynamicScreenSpaceErrorContainer);
  209. loggingPanelContents.appendChild(
  210. createCheckbox("Performance", "performance")
  211. );
  212. loggingPanelContents.appendChild(performanceContainer);
  213. loggingPanelContents.appendChild(
  214. createCheckbox("Statistics", "showStatistics")
  215. );
  216. const statistics = document.createElement("div");
  217. statistics.className = "cesium-3dTilesInspector-statistics";
  218. statistics.setAttribute(
  219. "data-bind",
  220. "html: statisticsText, visible: showStatistics"
  221. );
  222. loggingPanelContents.appendChild(statistics);
  223. loggingPanelContents.appendChild(
  224. createCheckbox("Pick Statistics", "showPickStatistics")
  225. );
  226. const pickStatistics = document.createElement("div");
  227. pickStatistics.className = "cesium-3dTilesInspector-statistics";
  228. pickStatistics.setAttribute(
  229. "data-bind",
  230. "html: pickStatisticsText, visible: showPickStatistics"
  231. );
  232. loggingPanelContents.appendChild(pickStatistics);
  233. loggingPanelContents.appendChild(
  234. createCheckbox("Resource Cache Statistics", "showResourceCacheStatistics")
  235. );
  236. const resourceCacheStatistics = document.createElement("div");
  237. resourceCacheStatistics.className = "cesium-3dTilesInspector-statistics";
  238. resourceCacheStatistics.setAttribute(
  239. "data-bind",
  240. "html: resourceCacheStatisticsText, visible: showResourceCacheStatistics"
  241. );
  242. loggingPanelContents.appendChild(resourceCacheStatistics);
  243. const stylePanelEditor = document.createElement("div");
  244. stylePanelContents.appendChild(stylePanelEditor);
  245. stylePanelEditor.appendChild(document.createTextNode("Color Blend Mode: "));
  246. const blendDropdown = document.createElement("select");
  247. blendDropdown.setAttribute(
  248. "data-bind",
  249. "options: colorBlendModes, " +
  250. 'optionsText: "text", ' +
  251. 'optionsValue: "value", ' +
  252. "value: colorBlendMode"
  253. );
  254. stylePanelEditor.appendChild(blendDropdown);
  255. const styleEditor = document.createElement("textarea");
  256. styleEditor.setAttribute(
  257. "data-bind",
  258. "textInput: styleString, event: { keydown: styleEditorKeyPress }"
  259. );
  260. stylePanelEditor.className = "cesium-cesiumInspector-styleEditor";
  261. stylePanelEditor.appendChild(styleEditor);
  262. const closeStylesBtn = createButton("Compile (Ctrl+Enter)", "compileStyle");
  263. stylePanelEditor.appendChild(closeStylesBtn);
  264. const errorBox = document.createElement("div");
  265. errorBox.className = "cesium-cesiumInspector-error";
  266. errorBox.setAttribute("data-bind", "text: editorError");
  267. stylePanelEditor.appendChild(errorBox);
  268. tileDebugLabelsPanelContents.appendChild(
  269. createCheckbox("Show Picked Only", "showOnlyPickedTileDebugLabel")
  270. );
  271. tileDebugLabelsPanelContents.appendChild(
  272. createCheckbox("Geometric Error", "showGeometricError")
  273. );
  274. tileDebugLabelsPanelContents.appendChild(
  275. createCheckbox("Rendering Statistics", "showRenderingStatistics")
  276. );
  277. tileDebugLabelsPanelContents.appendChild(
  278. createCheckbox("Memory Usage (MB)", "showMemoryUsage")
  279. );
  280. tileDebugLabelsPanelContents.appendChild(createCheckbox("Url", "showUrl"));
  281. optimizationPanelContents.appendChild(
  282. createCheckbox("Skip Tile LODs", "skipLevelOfDetail")
  283. );
  284. const skipScreenSpaceErrorFactorContainer = document.createElement("div");
  285. skipScreenSpaceErrorFactorContainer.appendChild(
  286. createRangeInput("Skip SSE Factor", "skipScreenSpaceErrorFactor", 1, 50, 1)
  287. );
  288. optimizationPanelContents.appendChild(skipScreenSpaceErrorFactorContainer);
  289. const baseScreenSpaceError = document.createElement("div");
  290. baseScreenSpaceError.appendChild(
  291. createRangeInput(
  292. "SSE before skipping LOD",
  293. "baseScreenSpaceError",
  294. 0,
  295. 4096,
  296. 1
  297. )
  298. );
  299. optimizationPanelContents.appendChild(baseScreenSpaceError);
  300. const skipLevelsContainer = document.createElement("div");
  301. skipLevelsContainer.appendChild(
  302. createRangeInput("Min. levels to skip", "skipLevels", 0, 10, 1)
  303. );
  304. optimizationPanelContents.appendChild(skipLevelsContainer);
  305. optimizationPanelContents.appendChild(
  306. createCheckbox(
  307. "Load only tiles that meet the max SSE.",
  308. "immediatelyLoadDesiredLevelOfDetail"
  309. )
  310. );
  311. optimizationPanelContents.appendChild(
  312. createCheckbox("Load siblings of visible tiles", "loadSiblings")
  313. );
  314. knockout.applyBindings(viewModel, element);
  315. }
  316. Object.defineProperties(Cesium3DTilesInspector.prototype, {
  317. /**
  318. * Gets the parent container.
  319. * @memberof Cesium3DTilesInspector.prototype
  320. *
  321. * @type {Element}
  322. */
  323. container: {
  324. get: function () {
  325. return this._container;
  326. },
  327. },
  328. /**
  329. * Gets the view model.
  330. * @memberof Cesium3DTilesInspector.prototype
  331. *
  332. * @type {Cesium3DTilesInspectorViewModel}
  333. */
  334. viewModel: {
  335. get: function () {
  336. return this._viewModel;
  337. },
  338. },
  339. });
  340. /**
  341. * @returns {boolean} true if the object has been destroyed, false otherwise.
  342. */
  343. Cesium3DTilesInspector.prototype.isDestroyed = function () {
  344. return false;
  345. };
  346. /**
  347. * Destroys the widget. Should be called if permanently
  348. * removing the widget from layout.
  349. */
  350. Cesium3DTilesInspector.prototype.destroy = function () {
  351. knockout.cleanNode(this._element);
  352. this._container.removeChild(this._element);
  353. this.viewModel.destroy();
  354. return destroyObject(this);
  355. };
  356. export default Cesium3DTilesInspector;