DebugCameraPrimitive.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. import Cartesian3 from '../Core/Cartesian3.js';
  2. import Color from '../Core/Color.js';
  3. import ColorGeometryInstanceAttribute from '../Core/ColorGeometryInstanceAttribute.js';
  4. import defaultValue from '../Core/defaultValue.js';
  5. import defined from '../Core/defined.js';
  6. import destroyObject from '../Core/destroyObject.js';
  7. import DeveloperError from '../Core/DeveloperError.js';
  8. import FrustumGeometry from '../Core/FrustumGeometry.js';
  9. import FrustumOutlineGeometry from '../Core/FrustumOutlineGeometry.js';
  10. import GeometryInstance from '../Core/GeometryInstance.js';
  11. import Matrix3 from '../Core/Matrix3.js';
  12. import OrthographicFrustum from '../Core/OrthographicFrustum.js';
  13. import OrthographicOffCenterFrustum from '../Core/OrthographicOffCenterFrustum.js';
  14. import PerspectiveFrustum from '../Core/PerspectiveFrustum.js';
  15. import PerspectiveOffCenterFrustum from '../Core/PerspectiveOffCenterFrustum.js';
  16. import Quaternion from '../Core/Quaternion.js';
  17. import PerInstanceColorAppearance from './PerInstanceColorAppearance.js';
  18. import Primitive from './Primitive.js';
  19. /**
  20. * Draws the outline of the camera's view frustum.
  21. *
  22. * @alias DebugCameraPrimitive
  23. * @constructor
  24. *
  25. * @param {Object} options Object with the following properties:
  26. * @param {Camera} options.camera The camera.
  27. * @param {Color} [options.color=Color.CYAN] The color of the debug outline.
  28. * @param {Boolean} [options.updateOnChange=true] Whether the primitive updates when the underlying camera changes.
  29. * @param {Boolean} [options.show=true] Determines if this primitive will be shown.
  30. * @param {Object} [options.id] A user-defined object to return when the instance is picked with {@link Scene#pick}.
  31. *
  32. * @example
  33. * primitives.add(new Cesium.DebugCameraPrimitive({
  34. * camera : camera,
  35. * color : Cesium.Color.YELLOW
  36. * }));
  37. */
  38. function DebugCameraPrimitive(options) {
  39. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  40. //>>includeStart('debug', pragmas.debug);
  41. if (!defined(options.camera)) {
  42. throw new DeveloperError('options.camera is required.');
  43. }
  44. //>>includeEnd('debug');
  45. this._camera = options.camera;
  46. this._color = defaultValue(options.color, Color.CYAN);
  47. this._updateOnChange = defaultValue(options.updateOnChange, true);
  48. /**
  49. * Determines if this primitive will be shown.
  50. *
  51. * @type Boolean
  52. * @default true
  53. */
  54. this.show = defaultValue(options.show, true);
  55. /**
  56. * User-defined value returned when the primitive is picked.
  57. *
  58. * @type {*}
  59. * @default undefined
  60. *
  61. * @see Scene#pick
  62. */
  63. this.id = options.id;
  64. this._id = undefined;
  65. this._outlinePrimitives = [];
  66. this._planesPrimitives = [];
  67. }
  68. var scratchRight = new Cartesian3();
  69. var scratchRotation = new Matrix3();
  70. var scratchOrientation = new Quaternion();
  71. var scratchPerspective = new PerspectiveFrustum();
  72. var scratchPerspectiveOffCenter = new PerspectiveOffCenterFrustum();
  73. var scratchOrthographic = new OrthographicFrustum();
  74. var scratchOrthographicOffCenter = new OrthographicOffCenterFrustum();
  75. var scratchColor = new Color();
  76. var scratchSplits = [1.0, 100000.0];
  77. /**
  78. * @private
  79. */
  80. DebugCameraPrimitive.prototype.update = function(frameState) {
  81. if (!this.show) {
  82. return;
  83. }
  84. var planesPrimitives = this._planesPrimitives;
  85. var outlinePrimitives = this._outlinePrimitives;
  86. var i;
  87. var length;
  88. if (this._updateOnChange) {
  89. // Recreate the primitive every frame
  90. length = planesPrimitives.length;
  91. for (i = 0; i < length; ++i) {
  92. outlinePrimitives[i] = outlinePrimitives[i] && outlinePrimitives[i].destroy();
  93. planesPrimitives[i] = planesPrimitives[i] && planesPrimitives[i].destroy();
  94. }
  95. planesPrimitives.length = 0;
  96. outlinePrimitives.length = 0;
  97. }
  98. if (planesPrimitives.length === 0) {
  99. var camera = this._camera;
  100. var cameraFrustum = camera.frustum;
  101. var frustum;
  102. if (cameraFrustum instanceof PerspectiveFrustum) {
  103. frustum = scratchPerspective;
  104. } else if (cameraFrustum instanceof PerspectiveOffCenterFrustum) {
  105. frustum = scratchPerspectiveOffCenter;
  106. } else if (cameraFrustum instanceof OrthographicFrustum) {
  107. frustum = scratchOrthographic;
  108. } else {
  109. frustum = scratchOrthographicOffCenter;
  110. }
  111. frustum = cameraFrustum.clone(frustum);
  112. var frustumSplits = frameState.frustumSplits;
  113. var numFrustums = frustumSplits.length - 1;
  114. if (numFrustums <= 0) {
  115. frustumSplits = scratchSplits; // Use near and far planes if no splits created
  116. frustumSplits[0] = this._camera.frustum.near;
  117. frustumSplits[1] = this._camera.frustum.far;
  118. numFrustums = 1;
  119. }
  120. var position = camera.positionWC;
  121. var direction = camera.directionWC;
  122. var up = camera.upWC;
  123. var right = camera.rightWC;
  124. right = Cartesian3.negate(right, scratchRight);
  125. var rotation = scratchRotation;
  126. Matrix3.setColumn(rotation, 0, right, rotation);
  127. Matrix3.setColumn(rotation, 1, up, rotation);
  128. Matrix3.setColumn(rotation, 2, direction, rotation);
  129. var orientation = Quaternion.fromRotationMatrix(rotation, scratchOrientation);
  130. planesPrimitives.length = outlinePrimitives.length = numFrustums;
  131. for (i = 0; i < numFrustums; ++i) {
  132. frustum.near = frustumSplits[i];
  133. frustum.far = frustumSplits[i + 1];
  134. planesPrimitives[i] = new Primitive({
  135. geometryInstances : new GeometryInstance({
  136. geometry : new FrustumGeometry({
  137. origin : position,
  138. orientation : orientation,
  139. frustum : frustum,
  140. _drawNearPlane : i === 0
  141. }),
  142. attributes : {
  143. color : ColorGeometryInstanceAttribute.fromColor(Color.fromAlpha(this._color, 0.1, scratchColor))
  144. },
  145. id : this.id,
  146. pickPrimitive : this
  147. }),
  148. appearance : new PerInstanceColorAppearance({
  149. translucent : true,
  150. flat : true
  151. }),
  152. asynchronous : false
  153. });
  154. outlinePrimitives[i] = new Primitive({
  155. geometryInstances : new GeometryInstance({
  156. geometry : new FrustumOutlineGeometry({
  157. origin : position,
  158. orientation : orientation,
  159. frustum : frustum,
  160. _drawNearPlane : i === 0
  161. }),
  162. attributes : {
  163. color : ColorGeometryInstanceAttribute.fromColor(this._color)
  164. },
  165. id : this.id,
  166. pickPrimitive : this
  167. }),
  168. appearance : new PerInstanceColorAppearance({
  169. translucent : false,
  170. flat : true
  171. }),
  172. asynchronous : false
  173. });
  174. }
  175. }
  176. length = planesPrimitives.length;
  177. for (i = 0; i < length; ++i) {
  178. outlinePrimitives[i].update(frameState);
  179. planesPrimitives[i].update(frameState);
  180. }
  181. };
  182. /**
  183. * Returns true if this object was destroyed; otherwise, false.
  184. * <p>
  185. * If this object was destroyed, it should not be used; calling any function other than
  186. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
  187. * </p>
  188. *
  189. * @returns {Boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>.
  190. *
  191. * @see DebugCameraPrimitive#destroy
  192. */
  193. DebugCameraPrimitive.prototype.isDestroyed = function() {
  194. return false;
  195. };
  196. /**
  197. * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
  198. * release of WebGL resources, instead of relying on the garbage collector to destroy this object.
  199. * <p>
  200. * Once an object is destroyed, it should not be used; calling any function other than
  201. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
  202. * assign the return value (<code>undefined</code>) to the object as done in the example.
  203. * </p>
  204. *
  205. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  206. *
  207. * @example
  208. * p = p && p.destroy();
  209. *
  210. * @see DebugCameraPrimitive#isDestroyed
  211. */
  212. DebugCameraPrimitive.prototype.destroy = function() {
  213. var length = this._planesPrimitives.length;
  214. for (var i = 0; i < length; ++i) {
  215. this._outlinePrimitives[i] = this._outlinePrimitives[i] && this._outlinePrimitives[i].destroy();
  216. this._planesPrimitives[i] = this._planesPrimitives[i] && this._planesPrimitives[i].destroy();
  217. }
  218. return destroyObject(this);
  219. };
  220. export default DebugCameraPrimitive;