VoxelInspector.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. import {
  2. Cartesian3,
  3. Math as CesiumMath,
  4. Check,
  5. destroyObject,
  6. Ellipsoid,
  7. getElement,
  8. VoxelShapeType,
  9. } from "@cesium/engine";
  10. import knockout from "../ThirdParty/knockout.js";
  11. import InspectorShared from "../InspectorShared.js";
  12. import VoxelInspectorViewModel from "./VoxelInspectorViewModel.js";
  13. /**
  14. * Inspector widget to aid in debugging voxels
  15. *
  16. * @alias VoxelInspector
  17. * @constructor
  18. *
  19. * @param {Element|string} container The DOM element or ID that will contain the widget.
  20. * @param {Scene} scene the Scene instance to use.
  21. */
  22. function VoxelInspector(container, scene) {
  23. //>>includeStart('debug', pragmas.debug);
  24. Check.defined("container", container);
  25. Check.typeOf.object("scene", scene);
  26. //>>includeEnd('debug');
  27. container = getElement(container);
  28. const element = document.createElement("div");
  29. const viewModel = new VoxelInspectorViewModel(scene);
  30. this._viewModel = viewModel;
  31. this._container = container;
  32. this._element = element;
  33. const text = document.createElement("div");
  34. text.textContent = "Voxel Inspector";
  35. text.className = "cesium-cesiumInspector-button";
  36. text.setAttribute("data-bind", "click: toggleInspector");
  37. element.appendChild(text);
  38. element.className = "cesium-cesiumInspector cesium-VoxelInspector";
  39. element.setAttribute(
  40. "data-bind",
  41. 'css: { "cesium-cesiumInspector-visible" : inspectorVisible, "cesium-cesiumInspector-hidden" : !inspectorVisible}'
  42. );
  43. container.appendChild(element);
  44. const panel = document.createElement("div");
  45. panel.className = "cesium-cesiumInspector-dropDown";
  46. element.appendChild(panel);
  47. const createSection = InspectorShared.createSection;
  48. const createCheckbox = InspectorShared.createCheckbox;
  49. const createRangeInput = InspectorShared.createRangeInput;
  50. const createButton = InspectorShared.createButton;
  51. const displayPanelContents = createSection(
  52. panel,
  53. "Display",
  54. "displayVisible",
  55. "toggleDisplay"
  56. );
  57. const transformPanelContents = createSection(
  58. panel,
  59. "Transform",
  60. "transformVisible",
  61. "toggleTransform"
  62. );
  63. const boundsPanelContents = createSection(
  64. panel,
  65. "Bounds",
  66. "boundsVisible",
  67. "toggleBounds"
  68. );
  69. const clippingPanelContents = createSection(
  70. panel,
  71. "Clipping",
  72. "clippingVisible",
  73. "toggleClipping"
  74. );
  75. const shaderPanelContents = createSection(
  76. panel,
  77. "Shader",
  78. "shaderVisible",
  79. "toggleShader"
  80. );
  81. // Display
  82. displayPanelContents.appendChild(createCheckbox("Depth Test", "depthTest"));
  83. displayPanelContents.appendChild(createCheckbox("Show", "show"));
  84. displayPanelContents.appendChild(
  85. createCheckbox("Disable Update", "disableUpdate")
  86. );
  87. displayPanelContents.appendChild(createCheckbox("Debug Draw", "debugDraw"));
  88. displayPanelContents.appendChild(createCheckbox("Jitter", "jitter"));
  89. displayPanelContents.appendChild(
  90. createCheckbox("Nearest Sampling", "nearestSampling")
  91. );
  92. displayPanelContents.appendChild(
  93. createRangeInput("Screen Space Error", "screenSpaceError", 0, 128)
  94. );
  95. displayPanelContents.appendChild(
  96. createRangeInput("Step Size", "stepSize", 0.0, 2.0)
  97. );
  98. // Transform
  99. const maxTrans = 10.0;
  100. const maxScale = 10.0;
  101. const maxAngle = CesiumMath.PI;
  102. transformPanelContents.appendChild(
  103. createRangeInput("Translation X", "translationX", -maxTrans, +maxTrans)
  104. );
  105. transformPanelContents.appendChild(
  106. createRangeInput("Translation Y", "translationY", -maxTrans, +maxTrans)
  107. );
  108. transformPanelContents.appendChild(
  109. createRangeInput("Translation Z", "translationZ", -maxTrans, +maxTrans)
  110. );
  111. transformPanelContents.appendChild(
  112. createRangeInput("Scale X", "scaleX", 0, +maxScale)
  113. );
  114. transformPanelContents.appendChild(
  115. createRangeInput("Scale Y", "scaleY", 0, +maxScale)
  116. );
  117. transformPanelContents.appendChild(
  118. createRangeInput("Scale Z", "scaleZ", 0, +maxScale)
  119. );
  120. transformPanelContents.appendChild(
  121. createRangeInput("Heading", "angleX", -maxAngle, +maxAngle)
  122. );
  123. transformPanelContents.appendChild(
  124. createRangeInput("Pitch", "angleY", -maxAngle, +maxAngle)
  125. );
  126. transformPanelContents.appendChild(
  127. createRangeInput("Roll", "angleZ", -maxAngle, +maxAngle)
  128. );
  129. // Bounds
  130. const boxMinBounds = VoxelShapeType.getMinBounds(VoxelShapeType.BOX);
  131. const boxMaxBounds = VoxelShapeType.getMaxBounds(VoxelShapeType.BOX);
  132. const ellipsoidMinBounds = Cartesian3.fromElements(
  133. VoxelShapeType.getMinBounds(VoxelShapeType.ELLIPSOID).x,
  134. VoxelShapeType.getMinBounds(VoxelShapeType.ELLIPSOID).y,
  135. -Ellipsoid.WGS84.maximumRadius,
  136. new Cartesian3()
  137. );
  138. const ellipsoidMaxBounds = Cartesian3.fromElements(
  139. VoxelShapeType.getMaxBounds(VoxelShapeType.ELLIPSOID).x,
  140. VoxelShapeType.getMaxBounds(VoxelShapeType.ELLIPSOID).y,
  141. +10000000.0,
  142. new Cartesian3()
  143. );
  144. const cylinderMinBounds = VoxelShapeType.getMinBounds(
  145. VoxelShapeType.CYLINDER
  146. );
  147. const cylinderMaxBounds = VoxelShapeType.getMaxBounds(
  148. VoxelShapeType.CYLINDER
  149. );
  150. makeCoordinateRange(
  151. "Max X",
  152. "Min X",
  153. "Max Y",
  154. "Min Y",
  155. "Max Z",
  156. "Min Z",
  157. "boundsBoxMaxX",
  158. "boundsBoxMinX",
  159. "boundsBoxMaxY",
  160. "boundsBoxMinY",
  161. "boundsBoxMaxZ",
  162. "boundsBoxMinZ",
  163. boxMinBounds,
  164. boxMaxBounds,
  165. "shapeIsBox",
  166. boundsPanelContents
  167. );
  168. makeCoordinateRange(
  169. "Max Longitude",
  170. "Min Longitude",
  171. "Max Latitude",
  172. "Min Latitude",
  173. "Max Height",
  174. "Min Height",
  175. "boundsEllipsoidMaxLongitude",
  176. "boundsEllipsoidMinLongitude",
  177. "boundsEllipsoidMaxLatitude",
  178. "boundsEllipsoidMinLatitude",
  179. "boundsEllipsoidMaxHeight",
  180. "boundsEllipsoidMinHeight",
  181. ellipsoidMinBounds,
  182. ellipsoidMaxBounds,
  183. "shapeIsEllipsoid",
  184. boundsPanelContents
  185. );
  186. makeCoordinateRange(
  187. "Max Radius",
  188. "Min Radius",
  189. "Max Height",
  190. "Min Height",
  191. "Max Angle",
  192. "Min Angle",
  193. "boundsCylinderMaxRadius",
  194. "boundsCylinderMinRadius",
  195. "boundsCylinderMaxHeight",
  196. "boundsCylinderMinHeight",
  197. "boundsCylinderMaxAngle",
  198. "boundsCylinderMinAngle",
  199. cylinderMinBounds,
  200. cylinderMaxBounds,
  201. "shapeIsCylinder",
  202. boundsPanelContents
  203. );
  204. // Clipping
  205. makeCoordinateRange(
  206. "Max X",
  207. "Min X",
  208. "Max Y",
  209. "Min Y",
  210. "Max Z",
  211. "Min Z",
  212. "clippingBoxMaxX",
  213. "clippingBoxMinX",
  214. "clippingBoxMaxY",
  215. "clippingBoxMinY",
  216. "clippingBoxMaxZ",
  217. "clippingBoxMinZ",
  218. boxMinBounds,
  219. boxMaxBounds,
  220. "shapeIsBox",
  221. clippingPanelContents
  222. );
  223. makeCoordinateRange(
  224. "Max Longitude",
  225. "Min Longitude",
  226. "Max Latitude",
  227. "Min Latitude",
  228. "Max Height",
  229. "Min Height",
  230. "clippingEllipsoidMaxLongitude",
  231. "clippingEllipsoidMinLongitude",
  232. "clippingEllipsoidMaxLatitude",
  233. "clippingEllipsoidMinLatitude",
  234. "clippingEllipsoidMaxHeight",
  235. "clippingEllipsoidMinHeight",
  236. ellipsoidMinBounds,
  237. ellipsoidMaxBounds,
  238. "shapeIsEllipsoid",
  239. clippingPanelContents
  240. );
  241. makeCoordinateRange(
  242. "Max Radius",
  243. "Min Radius",
  244. "Max Height",
  245. "Min Height",
  246. "Max Angle",
  247. "Min Angle",
  248. "clippingCylinderMaxRadius",
  249. "clippingCylinderMinRadius",
  250. "clippingCylinderMaxHeight",
  251. "clippingCylinderMinHeight",
  252. "clippingCylinderMaxAngle",
  253. "clippingCylinderMinAngle",
  254. cylinderMinBounds,
  255. cylinderMaxBounds,
  256. "shapeIsCylinder",
  257. clippingPanelContents
  258. );
  259. // Shader
  260. const shaderPanelEditor = document.createElement("div");
  261. shaderPanelContents.appendChild(shaderPanelEditor);
  262. const shaderEditor = document.createElement("textarea");
  263. shaderEditor.setAttribute(
  264. "data-bind",
  265. "textInput: shaderString, event: { keydown: shaderEditorKeyPress }"
  266. );
  267. shaderPanelEditor.className = "cesium-cesiumInspector-styleEditor";
  268. shaderPanelEditor.appendChild(shaderEditor);
  269. const compileShaderButton = createButton(
  270. "Compile (Ctrl+Enter)",
  271. "compileShader"
  272. );
  273. shaderPanelEditor.appendChild(compileShaderButton);
  274. const compilationText = document.createElement("label");
  275. compilationText.style.display = "block";
  276. compilationText.setAttribute(
  277. "data-bind",
  278. "text: shaderCompilationMessage, style: {color: shaderCompilationSuccess ? 'green' : 'red'}"
  279. );
  280. shaderPanelEditor.appendChild(compilationText);
  281. knockout.applyBindings(viewModel, element);
  282. }
  283. Object.defineProperties(VoxelInspector.prototype, {
  284. /**
  285. * Gets the parent container.
  286. * @memberof VoxelInspector.prototype
  287. *
  288. * @type {Element}
  289. */
  290. container: {
  291. get: function () {
  292. return this._container;
  293. },
  294. },
  295. /**
  296. * Gets the view model.
  297. * @memberof VoxelInspector.prototype
  298. *
  299. * @type {VoxelInspectorViewModel}
  300. */
  301. viewModel: {
  302. get: function () {
  303. return this._viewModel;
  304. },
  305. },
  306. });
  307. /**
  308. * @returns {boolean} true if the object has been destroyed, false otherwise.
  309. */
  310. VoxelInspector.prototype.isDestroyed = function () {
  311. return false;
  312. };
  313. /**
  314. * Destroys the widget. Should be called if permanently
  315. * removing the widget from layout.
  316. */
  317. VoxelInspector.prototype.destroy = function () {
  318. knockout.cleanNode(this._element);
  319. this._container.removeChild(this._element);
  320. this.viewModel.destroy();
  321. return destroyObject(this);
  322. };
  323. function makeCoordinateRange(
  324. maxXTitle,
  325. minXTitle,
  326. maxYTitle,
  327. minYTitle,
  328. maxZTitle,
  329. minZTitle,
  330. maxXVar,
  331. minXVar,
  332. maxYVar,
  333. minYVar,
  334. maxZVar,
  335. minZVar,
  336. defaultMinBounds,
  337. defaultMaxBounds,
  338. allowedShape,
  339. parentContainer
  340. ) {
  341. const createRangeInput = InspectorShared.createRangeInput;
  342. const min = defaultMinBounds;
  343. const max = defaultMaxBounds;
  344. const boundsElement = parentContainer.appendChild(
  345. document.createElement("div")
  346. );
  347. boundsElement.setAttribute("data-bind", `if: ${allowedShape}`);
  348. boundsElement.appendChild(createRangeInput(maxXTitle, maxXVar, min.x, max.x));
  349. boundsElement.appendChild(createRangeInput(minXTitle, minXVar, min.x, max.x));
  350. boundsElement.appendChild(createRangeInput(maxYTitle, maxYVar, min.y, max.y));
  351. boundsElement.appendChild(createRangeInput(minYTitle, minYVar, min.y, max.y));
  352. boundsElement.appendChild(createRangeInput(maxZTitle, maxZVar, min.z, max.z));
  353. boundsElement.appendChild(createRangeInput(minZTitle, minZVar, min.z, max.z));
  354. }
  355. export default VoxelInspector;