PlaneGeometryUpdater.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. import Cartesian3 from "../Core/Cartesian3.js";
  2. import Check from "../Core/Check.js";
  3. import Color from "../Core/Color.js";
  4. import ColorGeometryInstanceAttribute from "../Core/ColorGeometryInstanceAttribute.js";
  5. import defined from "../Core/defined.js";
  6. import DeveloperError from "../Core/DeveloperError.js";
  7. import DistanceDisplayConditionGeometryInstanceAttribute from "../Core/DistanceDisplayConditionGeometryInstanceAttribute.js";
  8. import GeometryInstance from "../Core/GeometryInstance.js";
  9. import Iso8601 from "../Core/Iso8601.js";
  10. import CesiumMath from "../Core/Math.js";
  11. import Matrix3 from "../Core/Matrix3.js";
  12. import Matrix4 from "../Core/Matrix4.js";
  13. import PlaneGeometry from "../Core/PlaneGeometry.js";
  14. import PlaneOutlineGeometry from "../Core/PlaneOutlineGeometry.js";
  15. import ShowGeometryInstanceAttribute from "../Core/ShowGeometryInstanceAttribute.js";
  16. import MaterialAppearance from "../Scene/MaterialAppearance.js";
  17. import PerInstanceColorAppearance from "../Scene/PerInstanceColorAppearance.js";
  18. import ColorMaterialProperty from "./ColorMaterialProperty.js";
  19. import DynamicGeometryUpdater from "./DynamicGeometryUpdater.js";
  20. import GeometryUpdater from "./GeometryUpdater.js";
  21. import Property from "./Property.js";
  22. const positionScratch = new Cartesian3();
  23. const scratchColor = new Color();
  24. function PlaneGeometryOptions(entity) {
  25. this.id = entity;
  26. this.vertexFormat = undefined;
  27. this.plane = undefined;
  28. this.dimensions = undefined;
  29. }
  30. /**
  31. * A {@link GeometryUpdater} for planes.
  32. * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}.
  33. * @alias PlaneGeometryUpdater
  34. * @constructor
  35. *
  36. * @param {Entity} entity The entity containing the geometry to be visualized.
  37. * @param {Scene} scene The scene where visualization is taking place.
  38. */
  39. function PlaneGeometryUpdater(entity, scene) {
  40. GeometryUpdater.call(this, {
  41. entity: entity,
  42. scene: scene,
  43. geometryOptions: new PlaneGeometryOptions(entity),
  44. geometryPropertyName: "plane",
  45. observedPropertyNames: ["availability", "position", "orientation", "plane"],
  46. });
  47. this._onEntityPropertyChanged(entity, "plane", entity.plane, undefined);
  48. }
  49. if (defined(Object.create)) {
  50. PlaneGeometryUpdater.prototype = Object.create(GeometryUpdater.prototype);
  51. PlaneGeometryUpdater.prototype.constructor = PlaneGeometryUpdater;
  52. }
  53. /**
  54. * Creates the geometry instance which represents the fill of the geometry.
  55. *
  56. * @param {JulianDate} time The time to use when retrieving initial attribute values.
  57. * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.
  58. *
  59. * @exception {DeveloperError} This instance does not represent a filled geometry.
  60. */
  61. PlaneGeometryUpdater.prototype.createFillGeometryInstance = function (time) {
  62. //>>includeStart('debug', pragmas.debug);
  63. Check.defined("time", time);
  64. if (!this._fillEnabled) {
  65. throw new DeveloperError(
  66. "This instance does not represent a filled geometry."
  67. );
  68. }
  69. //>>includeEnd('debug');
  70. const entity = this._entity;
  71. const isAvailable = entity.isAvailable(time);
  72. let attributes;
  73. let color;
  74. const show = new ShowGeometryInstanceAttribute(
  75. isAvailable &&
  76. entity.isShowing &&
  77. this._showProperty.getValue(time) &&
  78. this._fillProperty.getValue(time)
  79. );
  80. const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(
  81. time
  82. );
  83. const distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(
  84. distanceDisplayCondition
  85. );
  86. if (this._materialProperty instanceof ColorMaterialProperty) {
  87. let currentColor;
  88. if (
  89. defined(this._materialProperty.color) &&
  90. (this._materialProperty.color.isConstant || isAvailable)
  91. ) {
  92. currentColor = this._materialProperty.color.getValue(time, scratchColor);
  93. }
  94. if (!defined(currentColor)) {
  95. currentColor = Color.WHITE;
  96. }
  97. color = ColorGeometryInstanceAttribute.fromColor(currentColor);
  98. attributes = {
  99. show: show,
  100. distanceDisplayCondition: distanceDisplayConditionAttribute,
  101. color: color,
  102. };
  103. } else {
  104. attributes = {
  105. show: show,
  106. distanceDisplayCondition: distanceDisplayConditionAttribute,
  107. };
  108. }
  109. const planeGraphics = entity.plane;
  110. const options = this._options;
  111. let modelMatrix = entity.computeModelMatrix(time);
  112. const plane = Property.getValueOrDefault(
  113. planeGraphics.plane,
  114. time,
  115. options.plane
  116. );
  117. const dimensions = Property.getValueOrUndefined(
  118. planeGraphics.dimensions,
  119. time,
  120. options.dimensions
  121. );
  122. options.plane = plane;
  123. options.dimensions = dimensions;
  124. modelMatrix = createPrimitiveMatrix(
  125. plane,
  126. dimensions,
  127. modelMatrix,
  128. modelMatrix
  129. );
  130. return new GeometryInstance({
  131. id: entity,
  132. geometry: new PlaneGeometry(this._options),
  133. modelMatrix: modelMatrix,
  134. attributes: attributes,
  135. });
  136. };
  137. /**
  138. * Creates the geometry instance which represents the outline of the geometry.
  139. *
  140. * @param {JulianDate} time The time to use when retrieving initial attribute values.
  141. * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.
  142. *
  143. * @exception {DeveloperError} This instance does not represent an outlined geometry.
  144. */
  145. PlaneGeometryUpdater.prototype.createOutlineGeometryInstance = function (time) {
  146. //>>includeStart('debug', pragmas.debug);
  147. Check.defined("time", time);
  148. if (!this._outlineEnabled) {
  149. throw new DeveloperError(
  150. "This instance does not represent an outlined geometry."
  151. );
  152. }
  153. //>>includeEnd('debug');
  154. const entity = this._entity;
  155. const isAvailable = entity.isAvailable(time);
  156. const outlineColor = Property.getValueOrDefault(
  157. this._outlineColorProperty,
  158. time,
  159. Color.BLACK,
  160. scratchColor
  161. );
  162. const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(
  163. time
  164. );
  165. const planeGraphics = entity.plane;
  166. const options = this._options;
  167. let modelMatrix = entity.computeModelMatrix(time);
  168. const plane = Property.getValueOrDefault(
  169. planeGraphics.plane,
  170. time,
  171. options.plane
  172. );
  173. const dimensions = Property.getValueOrUndefined(
  174. planeGraphics.dimensions,
  175. time,
  176. options.dimensions
  177. );
  178. options.plane = plane;
  179. options.dimensions = dimensions;
  180. modelMatrix = createPrimitiveMatrix(
  181. plane,
  182. dimensions,
  183. modelMatrix,
  184. modelMatrix
  185. );
  186. return new GeometryInstance({
  187. id: entity,
  188. geometry: new PlaneOutlineGeometry(),
  189. modelMatrix: modelMatrix,
  190. attributes: {
  191. show: new ShowGeometryInstanceAttribute(
  192. isAvailable &&
  193. entity.isShowing &&
  194. this._showProperty.getValue(time) &&
  195. this._showOutlineProperty.getValue(time)
  196. ),
  197. color: ColorGeometryInstanceAttribute.fromColor(outlineColor),
  198. distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(
  199. distanceDisplayCondition
  200. ),
  201. },
  202. });
  203. };
  204. PlaneGeometryUpdater.prototype._isHidden = function (entity, plane) {
  205. return (
  206. !defined(plane.plane) ||
  207. !defined(plane.dimensions) ||
  208. !defined(entity.position) ||
  209. GeometryUpdater.prototype._isHidden.call(this, entity, plane)
  210. );
  211. };
  212. PlaneGeometryUpdater.prototype._getIsClosed = function (options) {
  213. return false;
  214. };
  215. PlaneGeometryUpdater.prototype._isDynamic = function (entity, plane) {
  216. return (
  217. !entity.position.isConstant || //
  218. !Property.isConstant(entity.orientation) || //
  219. !plane.plane.isConstant || //
  220. !plane.dimensions.isConstant || //
  221. !Property.isConstant(plane.outlineWidth)
  222. );
  223. };
  224. PlaneGeometryUpdater.prototype._setStaticOptions = function (entity, plane) {
  225. const isColorMaterial =
  226. this._materialProperty instanceof ColorMaterialProperty;
  227. const options = this._options;
  228. options.vertexFormat = isColorMaterial
  229. ? PerInstanceColorAppearance.VERTEX_FORMAT
  230. : MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat;
  231. options.plane = plane.plane.getValue(Iso8601.MINIMUM_VALUE, options.plane);
  232. options.dimensions = plane.dimensions.getValue(
  233. Iso8601.MINIMUM_VALUE,
  234. options.dimensions
  235. );
  236. };
  237. PlaneGeometryUpdater.DynamicGeometryUpdater = DynamicPlaneGeometryUpdater;
  238. /**
  239. * @private
  240. */
  241. function DynamicPlaneGeometryUpdater(
  242. geometryUpdater,
  243. primitives,
  244. groundPrimitives
  245. ) {
  246. DynamicGeometryUpdater.call(
  247. this,
  248. geometryUpdater,
  249. primitives,
  250. groundPrimitives
  251. );
  252. }
  253. if (defined(Object.create)) {
  254. DynamicPlaneGeometryUpdater.prototype = Object.create(
  255. DynamicGeometryUpdater.prototype
  256. );
  257. DynamicPlaneGeometryUpdater.prototype.constructor = DynamicPlaneGeometryUpdater;
  258. }
  259. DynamicPlaneGeometryUpdater.prototype._isHidden = function (
  260. entity,
  261. plane,
  262. time
  263. ) {
  264. const options = this._options;
  265. const position = Property.getValueOrUndefined(
  266. entity.position,
  267. time,
  268. positionScratch
  269. );
  270. return (
  271. !defined(position) ||
  272. !defined(options.plane) ||
  273. !defined(options.dimensions) ||
  274. DynamicGeometryUpdater.prototype._isHidden.call(this, entity, plane, time)
  275. );
  276. };
  277. DynamicPlaneGeometryUpdater.prototype._setOptions = function (
  278. entity,
  279. plane,
  280. time
  281. ) {
  282. const options = this._options;
  283. options.plane = Property.getValueOrDefault(plane.plane, time, options.plane);
  284. options.dimensions = Property.getValueOrUndefined(
  285. plane.dimensions,
  286. time,
  287. options.dimensions
  288. );
  289. };
  290. const scratchAxis = new Cartesian3();
  291. const scratchUp = new Cartesian3();
  292. const scratchTranslation = new Cartesian3();
  293. const scratchScale = new Cartesian3();
  294. const scratchRotation = new Matrix3();
  295. const scratchRotationScale = new Matrix3();
  296. const scratchLocalTransform = new Matrix4();
  297. function createPrimitiveMatrix(plane, dimensions, transform, result) {
  298. const normal = plane.normal;
  299. const distance = plane.distance;
  300. const translation = Cartesian3.multiplyByScalar(
  301. normal,
  302. -distance,
  303. scratchTranslation
  304. );
  305. let up = Cartesian3.clone(Cartesian3.UNIT_Z, scratchUp);
  306. if (
  307. CesiumMath.equalsEpsilon(
  308. Math.abs(Cartesian3.dot(up, normal)),
  309. 1.0,
  310. CesiumMath.EPSILON8
  311. )
  312. ) {
  313. up = Cartesian3.clone(Cartesian3.UNIT_Y, up);
  314. }
  315. const left = Cartesian3.cross(up, normal, scratchAxis);
  316. up = Cartesian3.cross(normal, left, up);
  317. Cartesian3.normalize(left, left);
  318. Cartesian3.normalize(up, up);
  319. const rotationMatrix = scratchRotation;
  320. Matrix3.setColumn(rotationMatrix, 0, left, rotationMatrix);
  321. Matrix3.setColumn(rotationMatrix, 1, up, rotationMatrix);
  322. Matrix3.setColumn(rotationMatrix, 2, normal, rotationMatrix);
  323. const scale = Cartesian3.fromElements(
  324. dimensions.x,
  325. dimensions.y,
  326. 1.0,
  327. scratchScale
  328. );
  329. const rotationScaleMatrix = Matrix3.multiplyByScale(
  330. rotationMatrix,
  331. scale,
  332. scratchRotationScale
  333. );
  334. const localTransform = Matrix4.fromRotationTranslation(
  335. rotationScaleMatrix,
  336. translation,
  337. scratchLocalTransform
  338. );
  339. return Matrix4.multiplyTransformation(transform, localTransform, result);
  340. }
  341. /**
  342. * @private
  343. */
  344. PlaneGeometryUpdater.createPrimitiveMatrix = createPrimitiveMatrix;
  345. export default PlaneGeometryUpdater;