FrustumGeometry-93211505.js 96 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166
  1. /* This file is automatically rebuilt by the Cesium build process. */
  2. define(['exports', './defined-26bd4a03', './Check-da037458', './defaultValue-f2e68450', './Math-fa6e45cb', './Cartesian2-2a723276', './defineProperties-6f7a50f2', './Transforms-65aba0a4', './ComponentDatatype-69643096', './GeometryAttribute-ed359d71', './GeometryAttributes-eecc9f43', './Plane-a1a3fd52', './VertexFormat-fbb91dc7'], function (exports, defined, Check, defaultValue, _Math, Cartesian2, defineProperties, Transforms, ComponentDatatype, GeometryAttribute, GeometryAttributes, Plane, VertexFormat) { 'use strict';
  3. /**
  4. * The culling volume defined by planes.
  5. *
  6. * @alias CullingVolume
  7. * @constructor
  8. *
  9. * @param {Cartesian4[]} [planes] An array of clipping planes.
  10. */
  11. function CullingVolume(planes) {
  12. /**
  13. * Each plane is represented by a Cartesian4 object, where the x, y, and z components
  14. * define the unit vector normal to the plane, and the w component is the distance of the
  15. * plane from the origin.
  16. * @type {Cartesian4[]}
  17. * @default []
  18. */
  19. this.planes = defaultValue.defaultValue(planes, []);
  20. }
  21. var faces = [new Cartesian2.Cartesian3(), new Cartesian2.Cartesian3(), new Cartesian2.Cartesian3()];
  22. Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.UNIT_X, faces[0]);
  23. Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.UNIT_Y, faces[1]);
  24. Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.UNIT_Z, faces[2]);
  25. var scratchPlaneCenter = new Cartesian2.Cartesian3();
  26. var scratchPlaneNormal = new Cartesian2.Cartesian3();
  27. var scratchPlane = new Plane.Plane(new Cartesian2.Cartesian3(1.0, 0.0, 0.0), 0.0);
  28. /**
  29. * Constructs a culling volume from a bounding sphere. Creates six planes that create a box containing the sphere.
  30. * The planes are aligned to the x, y, and z axes in world coordinates.
  31. *
  32. * @param {BoundingSphere} boundingSphere The bounding sphere used to create the culling volume.
  33. * @param {CullingVolume} [result] The object onto which to store the result.
  34. * @returns {CullingVolume} The culling volume created from the bounding sphere.
  35. */
  36. CullingVolume.fromBoundingSphere = function(boundingSphere, result) {
  37. //>>includeStart('debug', pragmas.debug);
  38. if (!defined.defined(boundingSphere)) {
  39. throw new Check.DeveloperError('boundingSphere is required.');
  40. }
  41. //>>includeEnd('debug');
  42. if (!defined.defined(result)) {
  43. result = new CullingVolume();
  44. }
  45. var length = faces.length;
  46. var planes = result.planes;
  47. planes.length = 2 * length;
  48. var center = boundingSphere.center;
  49. var radius = boundingSphere.radius;
  50. var planeIndex = 0;
  51. for (var i = 0; i < length; ++i) {
  52. var faceNormal = faces[i];
  53. var plane0 = planes[planeIndex];
  54. var plane1 = planes[planeIndex + 1];
  55. if (!defined.defined(plane0)) {
  56. plane0 = planes[planeIndex] = new Transforms.Cartesian4();
  57. }
  58. if (!defined.defined(plane1)) {
  59. plane1 = planes[planeIndex + 1] = new Transforms.Cartesian4();
  60. }
  61. Cartesian2.Cartesian3.multiplyByScalar(faceNormal, -radius, scratchPlaneCenter);
  62. Cartesian2.Cartesian3.add(center, scratchPlaneCenter, scratchPlaneCenter);
  63. plane0.x = faceNormal.x;
  64. plane0.y = faceNormal.y;
  65. plane0.z = faceNormal.z;
  66. plane0.w = -Cartesian2.Cartesian3.dot(faceNormal, scratchPlaneCenter);
  67. Cartesian2.Cartesian3.multiplyByScalar(faceNormal, radius, scratchPlaneCenter);
  68. Cartesian2.Cartesian3.add(center, scratchPlaneCenter, scratchPlaneCenter);
  69. plane1.x = -faceNormal.x;
  70. plane1.y = -faceNormal.y;
  71. plane1.z = -faceNormal.z;
  72. plane1.w = -Cartesian2.Cartesian3.dot(Cartesian2.Cartesian3.negate(faceNormal, scratchPlaneNormal), scratchPlaneCenter);
  73. planeIndex += 2;
  74. }
  75. return result;
  76. };
  77. /**
  78. * Determines whether a bounding volume intersects the culling volume.
  79. *
  80. * @param {Object} boundingVolume The bounding volume whose intersection with the culling volume is to be tested.
  81. * @returns {Intersect} Intersect.OUTSIDE, Intersect.INTERSECTING, or Intersect.INSIDE.
  82. */
  83. CullingVolume.prototype.computeVisibility = function(boundingVolume) {
  84. //>>includeStart('debug', pragmas.debug);
  85. if (!defined.defined(boundingVolume)) {
  86. throw new Check.DeveloperError('boundingVolume is required.');
  87. }
  88. //>>includeEnd('debug');
  89. var planes = this.planes;
  90. var intersecting = false;
  91. for (var k = 0, len = planes.length; k < len; ++k) {
  92. var result = boundingVolume.intersectPlane(Plane.Plane.fromCartesian4(planes[k], scratchPlane));
  93. if (result === Transforms.Intersect.OUTSIDE) {
  94. return Transforms.Intersect.OUTSIDE;
  95. } else if (result === Transforms.Intersect.INTERSECTING) {
  96. intersecting = true;
  97. }
  98. }
  99. return intersecting ? Transforms.Intersect.INTERSECTING : Transforms.Intersect.INSIDE;
  100. };
  101. /**
  102. * Determines whether a bounding volume intersects the culling volume.
  103. *
  104. * @param {Object} boundingVolume The bounding volume whose intersection with the culling volume is to be tested.
  105. * @param {Number} parentPlaneMask A bit mask from the boundingVolume's parent's check against the same culling
  106. * volume, such that if (planeMask & (1 << planeIndex) === 0), for k < 31, then
  107. * the parent (and therefore this) volume is completely inside plane[planeIndex]
  108. * and that plane check can be skipped.
  109. * @returns {Number} A plane mask as described above (which can be applied to this boundingVolume's children).
  110. *
  111. * @private
  112. */
  113. CullingVolume.prototype.computeVisibilityWithPlaneMask = function(boundingVolume, parentPlaneMask) {
  114. //>>includeStart('debug', pragmas.debug);
  115. if (!defined.defined(boundingVolume)) {
  116. throw new Check.DeveloperError('boundingVolume is required.');
  117. }
  118. if (!defined.defined(parentPlaneMask)) {
  119. throw new Check.DeveloperError('parentPlaneMask is required.');
  120. }
  121. //>>includeEnd('debug');
  122. if (parentPlaneMask === CullingVolume.MASK_OUTSIDE || parentPlaneMask === CullingVolume.MASK_INSIDE) {
  123. // parent is completely outside or completely inside, so this child is as well.
  124. return parentPlaneMask;
  125. }
  126. // Start with MASK_INSIDE (all zeros) so that after the loop, the return value can be compared with MASK_INSIDE.
  127. // (Because if there are fewer than 31 planes, the upper bits wont be changed.)
  128. var mask = CullingVolume.MASK_INSIDE;
  129. var planes = this.planes;
  130. for (var k = 0, len = planes.length; k < len; ++k) {
  131. // For k greater than 31 (since 31 is the maximum number of INSIDE/INTERSECTING bits we can store), skip the optimization.
  132. var flag = (k < 31) ? (1 << k) : 0;
  133. if (k < 31 && (parentPlaneMask & flag) === 0) {
  134. // boundingVolume is known to be INSIDE this plane.
  135. continue;
  136. }
  137. var result = boundingVolume.intersectPlane(Plane.Plane.fromCartesian4(planes[k], scratchPlane));
  138. if (result === Transforms.Intersect.OUTSIDE) {
  139. return CullingVolume.MASK_OUTSIDE;
  140. } else if (result === Transforms.Intersect.INTERSECTING) {
  141. mask |= flag;
  142. }
  143. }
  144. return mask;
  145. };
  146. /**
  147. * For plane masks (as used in {@link CullingVolume#computeVisibilityWithPlaneMask}), this special value
  148. * represents the case where the object bounding volume is entirely outside the culling volume.
  149. *
  150. * @type {Number}
  151. * @private
  152. */
  153. CullingVolume.MASK_OUTSIDE = 0xffffffff;
  154. /**
  155. * For plane masks (as used in {@link CullingVolume.prototype.computeVisibilityWithPlaneMask}), this value
  156. * represents the case where the object bounding volume is entirely inside the culling volume.
  157. *
  158. * @type {Number}
  159. * @private
  160. */
  161. CullingVolume.MASK_INSIDE = 0x00000000;
  162. /**
  163. * For plane masks (as used in {@link CullingVolume.prototype.computeVisibilityWithPlaneMask}), this value
  164. * represents the case where the object bounding volume (may) intersect all planes of the culling volume.
  165. *
  166. * @type {Number}
  167. * @private
  168. */
  169. CullingVolume.MASK_INDETERMINATE = 0x7fffffff;
  170. /**
  171. * The viewing frustum is defined by 6 planes.
  172. * Each plane is represented by a {@link Cartesian4} object, where the x, y, and z components
  173. * define the unit vector normal to the plane, and the w component is the distance of the
  174. * plane from the origin/camera position.
  175. *
  176. * @alias OrthographicOffCenterFrustum
  177. * @constructor
  178. *
  179. * @param {Object} [options] An object with the following properties:
  180. * @param {Number} [options.left] The left clipping plane distance.
  181. * @param {Number} [options.right] The right clipping plane distance.
  182. * @param {Number} [options.top] The top clipping plane distance.
  183. * @param {Number} [options.bottom] The bottom clipping plane distance.
  184. * @param {Number} [options.near=1.0] The near clipping plane distance.
  185. * @param {Number} [options.far=500000000.0] The far clipping plane distance.
  186. *
  187. * @example
  188. * var maxRadii = ellipsoid.maximumRadius;
  189. *
  190. * var frustum = new Cesium.OrthographicOffCenterFrustum();
  191. * frustum.right = maxRadii * Cesium.Math.PI;
  192. * frustum.left = -c.frustum.right;
  193. * frustum.top = c.frustum.right * (canvas.clientHeight / canvas.clientWidth);
  194. * frustum.bottom = -c.frustum.top;
  195. * frustum.near = 0.01 * maxRadii;
  196. * frustum.far = 50.0 * maxRadii;
  197. */
  198. function OrthographicOffCenterFrustum(options) {
  199. options = defaultValue.defaultValue(options, defaultValue.defaultValue.EMPTY_OBJECT);
  200. /**
  201. * The left clipping plane.
  202. * @type {Number}
  203. * @default undefined
  204. */
  205. this.left = options.left;
  206. this._left = undefined;
  207. /**
  208. * The right clipping plane.
  209. * @type {Number}
  210. * @default undefined
  211. */
  212. this.right = options.right;
  213. this._right = undefined;
  214. /**
  215. * The top clipping plane.
  216. * @type {Number}
  217. * @default undefined
  218. */
  219. this.top = options.top;
  220. this._top = undefined;
  221. /**
  222. * The bottom clipping plane.
  223. * @type {Number}
  224. * @default undefined
  225. */
  226. this.bottom = options.bottom;
  227. this._bottom = undefined;
  228. /**
  229. * The distance of the near plane.
  230. * @type {Number}
  231. * @default 1.0
  232. */
  233. this.near = defaultValue.defaultValue(options.near, 1.0);
  234. this._near = this.near;
  235. /**
  236. * The distance of the far plane.
  237. * @type {Number}
  238. * @default 500000000.0;
  239. */
  240. this.far = defaultValue.defaultValue(options.far, 500000000.0);
  241. this._far = this.far;
  242. this._cullingVolume = new CullingVolume();
  243. this._orthographicMatrix = new Transforms.Matrix4();
  244. }
  245. function update(frustum) {
  246. //>>includeStart('debug', pragmas.debug);
  247. if (!defined.defined(frustum.right) || !defined.defined(frustum.left) ||
  248. !defined.defined(frustum.top) || !defined.defined(frustum.bottom) ||
  249. !defined.defined(frustum.near) || !defined.defined(frustum.far)) {
  250. throw new Check.DeveloperError('right, left, top, bottom, near, or far parameters are not set.');
  251. }
  252. //>>includeEnd('debug');
  253. if (frustum.top !== frustum._top || frustum.bottom !== frustum._bottom ||
  254. frustum.left !== frustum._left || frustum.right !== frustum._right ||
  255. frustum.near !== frustum._near || frustum.far !== frustum._far) {
  256. //>>includeStart('debug', pragmas.debug);
  257. if (frustum.left > frustum.right) {
  258. throw new Check.DeveloperError('right must be greater than left.');
  259. }
  260. if (frustum.bottom > frustum.top) {
  261. throw new Check.DeveloperError('top must be greater than bottom.');
  262. }
  263. if (frustum.near <= 0 || frustum.near > frustum.far) {
  264. throw new Check.DeveloperError('near must be greater than zero and less than far.');
  265. }
  266. //>>includeEnd('debug');
  267. frustum._left = frustum.left;
  268. frustum._right = frustum.right;
  269. frustum._top = frustum.top;
  270. frustum._bottom = frustum.bottom;
  271. frustum._near = frustum.near;
  272. frustum._far = frustum.far;
  273. frustum._orthographicMatrix = Transforms.Matrix4.computeOrthographicOffCenter(frustum.left, frustum.right, frustum.bottom, frustum.top, frustum.near, frustum.far, frustum._orthographicMatrix);
  274. }
  275. }
  276. defineProperties.defineProperties(OrthographicOffCenterFrustum.prototype, {
  277. /**
  278. * Gets the orthographic projection matrix computed from the view frustum.
  279. * @memberof OrthographicOffCenterFrustum.prototype
  280. * @type {Matrix4}
  281. * @readonly
  282. */
  283. projectionMatrix : {
  284. get : function() {
  285. update(this);
  286. return this._orthographicMatrix;
  287. }
  288. }
  289. });
  290. var getPlanesRight = new Cartesian2.Cartesian3();
  291. var getPlanesNearCenter = new Cartesian2.Cartesian3();
  292. var getPlanesPoint = new Cartesian2.Cartesian3();
  293. var negateScratch = new Cartesian2.Cartesian3();
  294. /**
  295. * Creates a culling volume for this frustum.
  296. *
  297. * @param {Cartesian3} position The eye position.
  298. * @param {Cartesian3} direction The view direction.
  299. * @param {Cartesian3} up The up direction.
  300. * @returns {CullingVolume} A culling volume at the given position and orientation.
  301. *
  302. * @example
  303. * // Check if a bounding volume intersects the frustum.
  304. * var cullingVolume = frustum.computeCullingVolume(cameraPosition, cameraDirection, cameraUp);
  305. * var intersect = cullingVolume.computeVisibility(boundingVolume);
  306. */
  307. OrthographicOffCenterFrustum.prototype.computeCullingVolume = function(position, direction, up) {
  308. //>>includeStart('debug', pragmas.debug);
  309. if (!defined.defined(position)) {
  310. throw new Check.DeveloperError('position is required.');
  311. }
  312. if (!defined.defined(direction)) {
  313. throw new Check.DeveloperError('direction is required.');
  314. }
  315. if (!defined.defined(up)) {
  316. throw new Check.DeveloperError('up is required.');
  317. }
  318. //>>includeEnd('debug');
  319. var planes = this._cullingVolume.planes;
  320. var t = this.top;
  321. var b = this.bottom;
  322. var r = this.right;
  323. var l = this.left;
  324. var n = this.near;
  325. var f = this.far;
  326. var right = Cartesian2.Cartesian3.cross(direction, up, getPlanesRight);
  327. Cartesian2.Cartesian3.normalize(right, right);
  328. var nearCenter = getPlanesNearCenter;
  329. Cartesian2.Cartesian3.multiplyByScalar(direction, n, nearCenter);
  330. Cartesian2.Cartesian3.add(position, nearCenter, nearCenter);
  331. var point = getPlanesPoint;
  332. // Left plane
  333. Cartesian2.Cartesian3.multiplyByScalar(right, l, point);
  334. Cartesian2.Cartesian3.add(nearCenter, point, point);
  335. var plane = planes[0];
  336. if (!defined.defined(plane)) {
  337. plane = planes[0] = new Transforms.Cartesian4();
  338. }
  339. plane.x = right.x;
  340. plane.y = right.y;
  341. plane.z = right.z;
  342. plane.w = -Cartesian2.Cartesian3.dot(right, point);
  343. // Right plane
  344. Cartesian2.Cartesian3.multiplyByScalar(right, r, point);
  345. Cartesian2.Cartesian3.add(nearCenter, point, point);
  346. plane = planes[1];
  347. if (!defined.defined(plane)) {
  348. plane = planes[1] = new Transforms.Cartesian4();
  349. }
  350. plane.x = -right.x;
  351. plane.y = -right.y;
  352. plane.z = -right.z;
  353. plane.w = -Cartesian2.Cartesian3.dot(Cartesian2.Cartesian3.negate(right, negateScratch), point);
  354. // Bottom plane
  355. Cartesian2.Cartesian3.multiplyByScalar(up, b, point);
  356. Cartesian2.Cartesian3.add(nearCenter, point, point);
  357. plane = planes[2];
  358. if (!defined.defined(plane)) {
  359. plane = planes[2] = new Transforms.Cartesian4();
  360. }
  361. plane.x = up.x;
  362. plane.y = up.y;
  363. plane.z = up.z;
  364. plane.w = -Cartesian2.Cartesian3.dot(up, point);
  365. // Top plane
  366. Cartesian2.Cartesian3.multiplyByScalar(up, t, point);
  367. Cartesian2.Cartesian3.add(nearCenter, point, point);
  368. plane = planes[3];
  369. if (!defined.defined(plane)) {
  370. plane = planes[3] = new Transforms.Cartesian4();
  371. }
  372. plane.x = -up.x;
  373. plane.y = -up.y;
  374. plane.z = -up.z;
  375. plane.w = -Cartesian2.Cartesian3.dot(Cartesian2.Cartesian3.negate(up, negateScratch), point);
  376. // Near plane
  377. plane = planes[4];
  378. if (!defined.defined(plane)) {
  379. plane = planes[4] = new Transforms.Cartesian4();
  380. }
  381. plane.x = direction.x;
  382. plane.y = direction.y;
  383. plane.z = direction.z;
  384. plane.w = -Cartesian2.Cartesian3.dot(direction, nearCenter);
  385. // Far plane
  386. Cartesian2.Cartesian3.multiplyByScalar(direction, f, point);
  387. Cartesian2.Cartesian3.add(position, point, point);
  388. plane = planes[5];
  389. if (!defined.defined(plane)) {
  390. plane = planes[5] = new Transforms.Cartesian4();
  391. }
  392. plane.x = -direction.x;
  393. plane.y = -direction.y;
  394. plane.z = -direction.z;
  395. plane.w = -Cartesian2.Cartesian3.dot(Cartesian2.Cartesian3.negate(direction, negateScratch), point);
  396. return this._cullingVolume;
  397. };
  398. /**
  399. * Returns the pixel's width and height in meters.
  400. *
  401. * @param {Number} drawingBufferWidth The width of the drawing buffer.
  402. * @param {Number} drawingBufferHeight The height of the drawing buffer.
  403. * @param {Number} distance The distance to the near plane in meters.
  404. * @param {Number} pixelRatio The scaling factor from pixel space to coordinate space.
  405. * @param {Cartesian2} result The object onto which to store the result.
  406. * @returns {Cartesian2} The modified result parameter or a new instance of {@link Cartesian2} with the pixel's width and height in the x and y properties, respectively.
  407. *
  408. * @exception {DeveloperError} drawingBufferWidth must be greater than zero.
  409. * @exception {DeveloperError} drawingBufferHeight must be greater than zero.
  410. * @exception {DeveloperError} pixelRatio must be greater than zero.
  411. *
  412. * @example
  413. * // Example 1
  414. * // Get the width and height of a pixel.
  415. * var pixelSize = camera.frustum.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, 0.0, scene.pixelRatio, new Cesium.Cartesian2());
  416. */
  417. OrthographicOffCenterFrustum.prototype.getPixelDimensions = function(drawingBufferWidth, drawingBufferHeight, distance, pixelRatio, result) {
  418. update(this);
  419. if (pixelRatio instanceof Cartesian2.Cartesian2) {
  420. result = pixelRatio;
  421. pixelRatio = 1.0;
  422. Transforms.deprecationWarning('getPixelDimensions-parameter-change', 'getPixelDimensions now takes a pixelRatio argument before the result argument in Cesium 1.63. The previous function definition will no longer work in 1.65.');
  423. }
  424. //>>includeStart('debug', pragmas.debug);
  425. if (!defined.defined(drawingBufferWidth) || !defined.defined(drawingBufferHeight)) {
  426. throw new Check.DeveloperError('Both drawingBufferWidth and drawingBufferHeight are required.');
  427. }
  428. if (drawingBufferWidth <= 0) {
  429. throw new Check.DeveloperError('drawingBufferWidth must be greater than zero.');
  430. }
  431. if (drawingBufferHeight <= 0) {
  432. throw new Check.DeveloperError('drawingBufferHeight must be greater than zero.');
  433. }
  434. if (!defined.defined(distance)) {
  435. throw new Check.DeveloperError('distance is required.');
  436. }
  437. if (!defined.defined(pixelRatio)) {
  438. throw new Check.DeveloperError('pixelRatio is required.');
  439. }
  440. if (pixelRatio <= 0) {
  441. throw new Check.DeveloperError('pixelRatio must be greater than zero.');
  442. }
  443. if (!defined.defined(result)) {
  444. throw new Check.DeveloperError('A result object is required.');
  445. }
  446. //>>includeEnd('debug');
  447. var frustumWidth = this.right - this.left;
  448. var frustumHeight = this.top - this.bottom;
  449. var pixelWidth = pixelRatio * frustumWidth / drawingBufferWidth;
  450. var pixelHeight = pixelRatio * frustumHeight / drawingBufferHeight;
  451. result.x = pixelWidth;
  452. result.y = pixelHeight;
  453. return result;
  454. };
  455. /**
  456. * Returns a duplicate of a OrthographicOffCenterFrustum instance.
  457. *
  458. * @param {OrthographicOffCenterFrustum} [result] The object onto which to store the result.
  459. * @returns {OrthographicOffCenterFrustum} The modified result parameter or a new OrthographicOffCenterFrustum instance if one was not provided.
  460. */
  461. OrthographicOffCenterFrustum.prototype.clone = function(result) {
  462. if (!defined.defined(result)) {
  463. result = new OrthographicOffCenterFrustum();
  464. }
  465. result.left = this.left;
  466. result.right = this.right;
  467. result.top = this.top;
  468. result.bottom = this.bottom;
  469. result.near = this.near;
  470. result.far = this.far;
  471. // force update of clone to compute matrices
  472. result._left = undefined;
  473. result._right = undefined;
  474. result._top = undefined;
  475. result._bottom = undefined;
  476. result._near = undefined;
  477. result._far = undefined;
  478. return result;
  479. };
  480. /**
  481. * Compares the provided OrthographicOffCenterFrustum componentwise and returns
  482. * <code>true</code> if they are equal, <code>false</code> otherwise.
  483. *
  484. * @param {OrthographicOffCenterFrustum} [other] The right hand side OrthographicOffCenterFrustum.
  485. * @returns {Boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
  486. */
  487. OrthographicOffCenterFrustum.prototype.equals = function(other) {
  488. return (defined.defined(other) && other instanceof OrthographicOffCenterFrustum &&
  489. this.right === other.right &&
  490. this.left === other.left &&
  491. this.top === other.top &&
  492. this.bottom === other.bottom &&
  493. this.near === other.near &&
  494. this.far === other.far);
  495. };
  496. /**
  497. * Compares the provided OrthographicOffCenterFrustum componentwise and returns
  498. * <code>true</code> if they pass an absolute or relative tolerance test,
  499. * <code>false</code> otherwise.
  500. *
  501. * @param {OrthographicOffCenterFrustum} other The right hand side OrthographicOffCenterFrustum.
  502. * @param {Number} relativeEpsilon The relative epsilon tolerance to use for equality testing.
  503. * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.
  504. * @returns {Boolean} <code>true</code> if this and other are within the provided epsilon, <code>false</code> otherwise.
  505. */
  506. OrthographicOffCenterFrustum.prototype.equalsEpsilon = function(other, relativeEpsilon, absoluteEpsilon) {
  507. return (other === this) ||
  508. (defined.defined(other) &&
  509. other instanceof OrthographicOffCenterFrustum &&
  510. _Math.CesiumMath.equalsEpsilon(this.right, other.right, relativeEpsilon, absoluteEpsilon) &&
  511. _Math.CesiumMath.equalsEpsilon(this.left, other.left, relativeEpsilon, absoluteEpsilon) &&
  512. _Math.CesiumMath.equalsEpsilon(this.top, other.top, relativeEpsilon, absoluteEpsilon) &&
  513. _Math.CesiumMath.equalsEpsilon(this.bottom, other.bottom, relativeEpsilon, absoluteEpsilon) &&
  514. _Math.CesiumMath.equalsEpsilon(this.near, other.near, relativeEpsilon, absoluteEpsilon) &&
  515. _Math.CesiumMath.equalsEpsilon(this.far, other.far, relativeEpsilon, absoluteEpsilon));
  516. };
  517. /**
  518. * The viewing frustum is defined by 6 planes.
  519. * Each plane is represented by a {@link Cartesian4} object, where the x, y, and z components
  520. * define the unit vector normal to the plane, and the w component is the distance of the
  521. * plane from the origin/camera position.
  522. *
  523. * @alias OrthographicFrustum
  524. * @constructor
  525. *
  526. * @param {Object} [options] An object with the following properties:
  527. * @param {Number} [options.width] The width of the frustum in meters.
  528. * @param {Number} [options.aspectRatio] The aspect ratio of the frustum's width to it's height.
  529. * @param {Number} [options.near=1.0] The distance of the near plane.
  530. * @param {Number} [options.far=500000000.0] The distance of the far plane.
  531. *
  532. * @example
  533. * var maxRadii = ellipsoid.maximumRadius;
  534. *
  535. * var frustum = new Cesium.OrthographicFrustum();
  536. * frustum.near = 0.01 * maxRadii;
  537. * frustum.far = 50.0 * maxRadii;
  538. */
  539. function OrthographicFrustum(options) {
  540. options = defaultValue.defaultValue(options, defaultValue.defaultValue.EMPTY_OBJECT);
  541. this._offCenterFrustum = new OrthographicOffCenterFrustum();
  542. /**
  543. * The horizontal width of the frustum in meters.
  544. * @type {Number}
  545. * @default undefined
  546. */
  547. this.width = options.width;
  548. this._width = undefined;
  549. /**
  550. * The aspect ratio of the frustum's width to it's height.
  551. * @type {Number}
  552. * @default undefined
  553. */
  554. this.aspectRatio = options.aspectRatio;
  555. this._aspectRatio = undefined;
  556. /**
  557. * The distance of the near plane.
  558. * @type {Number}
  559. * @default 1.0
  560. */
  561. this.near = defaultValue.defaultValue(options.near, 1.0);
  562. this._near = this.near;
  563. /**
  564. * The distance of the far plane.
  565. * @type {Number}
  566. * @default 500000000.0;
  567. */
  568. this.far = defaultValue.defaultValue(options.far, 500000000.0);
  569. this._far = this.far;
  570. }
  571. /**
  572. * The number of elements used to pack the object into an array.
  573. * @type {Number}
  574. */
  575. OrthographicFrustum.packedLength = 4;
  576. /**
  577. * Stores the provided instance into the provided array.
  578. *
  579. * @param {OrthographicFrustum} value The value to pack.
  580. * @param {Number[]} array The array to pack into.
  581. * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.
  582. *
  583. * @returns {Number[]} The array that was packed into
  584. */
  585. OrthographicFrustum.pack = function(value, array, startingIndex) {
  586. //>>includeStart('debug', pragmas.debug);
  587. Check.Check.typeOf.object('value', value);
  588. Check.Check.defined('array', array);
  589. //>>includeEnd('debug');
  590. startingIndex = defaultValue.defaultValue(startingIndex, 0);
  591. array[startingIndex++] = value.width;
  592. array[startingIndex++] = value.aspectRatio;
  593. array[startingIndex++] = value.near;
  594. array[startingIndex] = value.far;
  595. return array;
  596. };
  597. /**
  598. * Retrieves an instance from a packed array.
  599. *
  600. * @param {Number[]} array The packed array.
  601. * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.
  602. * @param {OrthographicFrustum} [result] The object into which to store the result.
  603. * @returns {OrthographicFrustum} The modified result parameter or a new OrthographicFrustum instance if one was not provided.
  604. */
  605. OrthographicFrustum.unpack = function(array, startingIndex, result) {
  606. //>>includeStart('debug', pragmas.debug);
  607. Check.Check.defined('array', array);
  608. //>>includeEnd('debug');
  609. startingIndex = defaultValue.defaultValue(startingIndex, 0);
  610. if (!defined.defined(result)) {
  611. result = new OrthographicFrustum();
  612. }
  613. result.width = array[startingIndex++];
  614. result.aspectRatio = array[startingIndex++];
  615. result.near = array[startingIndex++];
  616. result.far = array[startingIndex];
  617. return result;
  618. };
  619. function update$1(frustum) {
  620. //>>includeStart('debug', pragmas.debug);
  621. if (!defined.defined(frustum.width) || !defined.defined(frustum.aspectRatio) || !defined.defined(frustum.near) || !defined.defined(frustum.far)) {
  622. throw new Check.DeveloperError('width, aspectRatio, near, or far parameters are not set.');
  623. }
  624. //>>includeEnd('debug');
  625. var f = frustum._offCenterFrustum;
  626. if (frustum.width !== frustum._width || frustum.aspectRatio !== frustum._aspectRatio ||
  627. frustum.near !== frustum._near || frustum.far !== frustum._far) {
  628. //>>includeStart('debug', pragmas.debug);
  629. if (frustum.aspectRatio < 0) {
  630. throw new Check.DeveloperError('aspectRatio must be positive.');
  631. }
  632. if (frustum.near < 0 || frustum.near > frustum.far) {
  633. throw new Check.DeveloperError('near must be greater than zero and less than far.');
  634. }
  635. //>>includeEnd('debug');
  636. frustum._aspectRatio = frustum.aspectRatio;
  637. frustum._width = frustum.width;
  638. frustum._near = frustum.near;
  639. frustum._far = frustum.far;
  640. var ratio = 1.0 / frustum.aspectRatio;
  641. f.right = frustum.width * 0.5;
  642. f.left = -f.right;
  643. f.top = ratio * f.right;
  644. f.bottom = -f.top;
  645. f.near = frustum.near;
  646. f.far = frustum.far;
  647. }
  648. }
  649. defineProperties.defineProperties(OrthographicFrustum.prototype, {
  650. /**
  651. * Gets the orthographic projection matrix computed from the view frustum.
  652. * @memberof OrthographicFrustum.prototype
  653. * @type {Matrix4}
  654. * @readonly
  655. */
  656. projectionMatrix : {
  657. get : function() {
  658. update$1(this);
  659. return this._offCenterFrustum.projectionMatrix;
  660. }
  661. }
  662. });
  663. /**
  664. * Creates a culling volume for this frustum.
  665. *
  666. * @param {Cartesian3} position The eye position.
  667. * @param {Cartesian3} direction The view direction.
  668. * @param {Cartesian3} up The up direction.
  669. * @returns {CullingVolume} A culling volume at the given position and orientation.
  670. *
  671. * @example
  672. * // Check if a bounding volume intersects the frustum.
  673. * var cullingVolume = frustum.computeCullingVolume(cameraPosition, cameraDirection, cameraUp);
  674. * var intersect = cullingVolume.computeVisibility(boundingVolume);
  675. */
  676. OrthographicFrustum.prototype.computeCullingVolume = function(position, direction, up) {
  677. update$1(this);
  678. return this._offCenterFrustum.computeCullingVolume(position, direction, up);
  679. };
  680. /**
  681. * Returns the pixel's width and height in meters.
  682. *
  683. * @param {Number} drawingBufferWidth The width of the drawing buffer.
  684. * @param {Number} drawingBufferHeight The height of the drawing buffer.
  685. * @param {Number} distance The distance to the near plane in meters.
  686. * @param {Number} pixelRatio The scaling factor from pixel space to coordinate space.
  687. * @param {Cartesian2} result The object onto which to store the result.
  688. * @returns {Cartesian2} The modified result parameter or a new instance of {@link Cartesian2} with the pixel's width and height in the x and y properties, respectively.
  689. *
  690. * @exception {DeveloperError} drawingBufferWidth must be greater than zero.
  691. * @exception {DeveloperError} drawingBufferHeight must be greater than zero.
  692. * @exception {DeveloperError} pixelRatio must be greater than zero.
  693. *
  694. * @example
  695. * // Example 1
  696. * // Get the width and height of a pixel.
  697. * var pixelSize = camera.frustum.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, 0.0, scene.pixelRatio, new Cesium.Cartesian2());
  698. */
  699. OrthographicFrustum.prototype.getPixelDimensions = function(drawingBufferWidth, drawingBufferHeight, distance, pixelRatio, result) {
  700. update$1(this);
  701. if (pixelRatio instanceof Cartesian2.Cartesian2) {
  702. result = pixelRatio;
  703. pixelRatio = 1.0;
  704. Transforms.deprecationWarning('getPixelDimensions-parameter-change', 'getPixelDimensions now takes a pixelRatio argument before the result argument in Cesium 1.63. The previous function definition will no longer work in 1.65.');
  705. }
  706. return this._offCenterFrustum.getPixelDimensions(drawingBufferWidth, drawingBufferHeight, distance, pixelRatio, result);
  707. };
  708. /**
  709. * Returns a duplicate of a OrthographicFrustum instance.
  710. *
  711. * @param {OrthographicFrustum} [result] The object onto which to store the result.
  712. * @returns {OrthographicFrustum} The modified result parameter or a new OrthographicFrustum instance if one was not provided.
  713. */
  714. OrthographicFrustum.prototype.clone = function(result) {
  715. if (!defined.defined(result)) {
  716. result = new OrthographicFrustum();
  717. }
  718. result.aspectRatio = this.aspectRatio;
  719. result.width = this.width;
  720. result.near = this.near;
  721. result.far = this.far;
  722. // force update of clone to compute matrices
  723. result._aspectRatio = undefined;
  724. result._width = undefined;
  725. result._near = undefined;
  726. result._far = undefined;
  727. this._offCenterFrustum.clone(result._offCenterFrustum);
  728. return result;
  729. };
  730. /**
  731. * Compares the provided OrthographicFrustum componentwise and returns
  732. * <code>true</code> if they are equal, <code>false</code> otherwise.
  733. *
  734. * @param {OrthographicFrustum} [other] The right hand side OrthographicFrustum.
  735. * @returns {Boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
  736. */
  737. OrthographicFrustum.prototype.equals = function(other) {
  738. if (!defined.defined(other) || !(other instanceof OrthographicFrustum)) {
  739. return false;
  740. }
  741. update$1(this);
  742. update$1(other);
  743. return (this.width === other.width &&
  744. this.aspectRatio === other.aspectRatio &&
  745. this._offCenterFrustum.equals(other._offCenterFrustum));
  746. };
  747. /**
  748. * Compares the provided OrthographicFrustum componentwise and returns
  749. * <code>true</code> if they pass an absolute or relative tolerance test,
  750. * <code>false</code> otherwise.
  751. *
  752. * @param {OrthographicFrustum} other The right hand side OrthographicFrustum.
  753. * @param {Number} relativeEpsilon The relative epsilon tolerance to use for equality testing.
  754. * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.
  755. * @returns {Boolean} <code>true</code> if this and other are within the provided epsilon, <code>false</code> otherwise.
  756. */
  757. OrthographicFrustum.prototype.equalsEpsilon = function(other, relativeEpsilon, absoluteEpsilon) {
  758. if (!defined.defined(other) || !(other instanceof OrthographicFrustum)) {
  759. return false;
  760. }
  761. update$1(this);
  762. update$1(other);
  763. return (_Math.CesiumMath.equalsEpsilon(this.width, other.width, relativeEpsilon, absoluteEpsilon) &&
  764. _Math.CesiumMath.equalsEpsilon(this.aspectRatio, other.aspectRatio, relativeEpsilon, absoluteEpsilon) &&
  765. this._offCenterFrustum.equalsEpsilon(other._offCenterFrustum, relativeEpsilon, absoluteEpsilon));
  766. };
  767. /**
  768. * The viewing frustum is defined by 6 planes.
  769. * Each plane is represented by a {@link Cartesian4} object, where the x, y, and z components
  770. * define the unit vector normal to the plane, and the w component is the distance of the
  771. * plane from the origin/camera position.
  772. *
  773. * @alias PerspectiveOffCenterFrustum
  774. * @constructor
  775. *
  776. * @param {Object} [options] An object with the following properties:
  777. * @param {Number} [options.left] The left clipping plane distance.
  778. * @param {Number} [options.right] The right clipping plane distance.
  779. * @param {Number} [options.top] The top clipping plane distance.
  780. * @param {Number} [options.bottom] The bottom clipping plane distance.
  781. * @param {Number} [options.near=1.0] The near clipping plane distance.
  782. * @param {Number} [options.far=500000000.0] The far clipping plane distance.
  783. *
  784. * @example
  785. * var frustum = new Cesium.PerspectiveOffCenterFrustum({
  786. * left : -1.0,
  787. * right : 1.0,
  788. * top : 1.0,
  789. * bottom : -1.0,
  790. * near : 1.0,
  791. * far : 100.0
  792. * });
  793. *
  794. * @see PerspectiveFrustum
  795. */
  796. function PerspectiveOffCenterFrustum(options) {
  797. options = defaultValue.defaultValue(options, defaultValue.defaultValue.EMPTY_OBJECT);
  798. /**
  799. * Defines the left clipping plane.
  800. * @type {Number}
  801. * @default undefined
  802. */
  803. this.left = options.left;
  804. this._left = undefined;
  805. /**
  806. * Defines the right clipping plane.
  807. * @type {Number}
  808. * @default undefined
  809. */
  810. this.right = options.right;
  811. this._right = undefined;
  812. /**
  813. * Defines the top clipping plane.
  814. * @type {Number}
  815. * @default undefined
  816. */
  817. this.top = options.top;
  818. this._top = undefined;
  819. /**
  820. * Defines the bottom clipping plane.
  821. * @type {Number}
  822. * @default undefined
  823. */
  824. this.bottom = options.bottom;
  825. this._bottom = undefined;
  826. /**
  827. * The distance of the near plane.
  828. * @type {Number}
  829. * @default 1.0
  830. */
  831. this.near = defaultValue.defaultValue(options.near, 1.0);
  832. this._near = this.near;
  833. /**
  834. * The distance of the far plane.
  835. * @type {Number}
  836. * @default 500000000.0
  837. */
  838. this.far = defaultValue.defaultValue(options.far, 500000000.0);
  839. this._far = this.far;
  840. this._cullingVolume = new CullingVolume();
  841. this._perspectiveMatrix = new Transforms.Matrix4();
  842. this._infinitePerspective = new Transforms.Matrix4();
  843. }
  844. function update$2(frustum) {
  845. //>>includeStart('debug', pragmas.debug);
  846. if (!defined.defined(frustum.right) || !defined.defined(frustum.left) ||
  847. !defined.defined(frustum.top) || !defined.defined(frustum.bottom) ||
  848. !defined.defined(frustum.near) || !defined.defined(frustum.far)) {
  849. throw new Check.DeveloperError('right, left, top, bottom, near, or far parameters are not set.');
  850. }
  851. //>>includeEnd('debug');
  852. var t = frustum.top;
  853. var b = frustum.bottom;
  854. var r = frustum.right;
  855. var l = frustum.left;
  856. var n = frustum.near;
  857. var f = frustum.far;
  858. if (t !== frustum._top || b !== frustum._bottom ||
  859. l !== frustum._left || r !== frustum._right ||
  860. n !== frustum._near || f !== frustum._far) {
  861. //>>includeStart('debug', pragmas.debug);
  862. if (frustum.near <= 0 || frustum.near > frustum.far) {
  863. throw new Check.DeveloperError('near must be greater than zero and less than far.');
  864. }
  865. //>>includeEnd('debug');
  866. frustum._left = l;
  867. frustum._right = r;
  868. frustum._top = t;
  869. frustum._bottom = b;
  870. frustum._near = n;
  871. frustum._far = f;
  872. frustum._perspectiveMatrix = Transforms.Matrix4.computePerspectiveOffCenter(l, r, b, t, n, f, frustum._perspectiveMatrix);
  873. frustum._infinitePerspective = Transforms.Matrix4.computeInfinitePerspectiveOffCenter(l, r, b, t, n, frustum._infinitePerspective);
  874. }
  875. }
  876. defineProperties.defineProperties(PerspectiveOffCenterFrustum.prototype, {
  877. /**
  878. * Gets the perspective projection matrix computed from the view frustum.
  879. * @memberof PerspectiveOffCenterFrustum.prototype
  880. * @type {Matrix4}
  881. * @readonly
  882. *
  883. * @see PerspectiveOffCenterFrustum#infiniteProjectionMatrix
  884. */
  885. projectionMatrix : {
  886. get : function() {
  887. update$2(this);
  888. return this._perspectiveMatrix;
  889. }
  890. },
  891. /**
  892. * Gets the perspective projection matrix computed from the view frustum with an infinite far plane.
  893. * @memberof PerspectiveOffCenterFrustum.prototype
  894. * @type {Matrix4}
  895. * @readonly
  896. *
  897. * @see PerspectiveOffCenterFrustum#projectionMatrix
  898. */
  899. infiniteProjectionMatrix : {
  900. get : function() {
  901. update$2(this);
  902. return this._infinitePerspective;
  903. }
  904. }
  905. });
  906. var getPlanesRight$1 = new Cartesian2.Cartesian3();
  907. var getPlanesNearCenter$1 = new Cartesian2.Cartesian3();
  908. var getPlanesFarCenter = new Cartesian2.Cartesian3();
  909. var getPlanesNormal = new Cartesian2.Cartesian3();
  910. /**
  911. * Creates a culling volume for this frustum.
  912. *
  913. * @param {Cartesian3} position The eye position.
  914. * @param {Cartesian3} direction The view direction.
  915. * @param {Cartesian3} up The up direction.
  916. * @returns {CullingVolume} A culling volume at the given position and orientation.
  917. *
  918. * @example
  919. * // Check if a bounding volume intersects the frustum.
  920. * var cullingVolume = frustum.computeCullingVolume(cameraPosition, cameraDirection, cameraUp);
  921. * var intersect = cullingVolume.computeVisibility(boundingVolume);
  922. */
  923. PerspectiveOffCenterFrustum.prototype.computeCullingVolume = function(position, direction, up) {
  924. //>>includeStart('debug', pragmas.debug);
  925. if (!defined.defined(position)) {
  926. throw new Check.DeveloperError('position is required.');
  927. }
  928. if (!defined.defined(direction)) {
  929. throw new Check.DeveloperError('direction is required.');
  930. }
  931. if (!defined.defined(up)) {
  932. throw new Check.DeveloperError('up is required.');
  933. }
  934. //>>includeEnd('debug');
  935. var planes = this._cullingVolume.planes;
  936. var t = this.top;
  937. var b = this.bottom;
  938. var r = this.right;
  939. var l = this.left;
  940. var n = this.near;
  941. var f = this.far;
  942. var right = Cartesian2.Cartesian3.cross(direction, up, getPlanesRight$1);
  943. var nearCenter = getPlanesNearCenter$1;
  944. Cartesian2.Cartesian3.multiplyByScalar(direction, n, nearCenter);
  945. Cartesian2.Cartesian3.add(position, nearCenter, nearCenter);
  946. var farCenter = getPlanesFarCenter;
  947. Cartesian2.Cartesian3.multiplyByScalar(direction, f, farCenter);
  948. Cartesian2.Cartesian3.add(position, farCenter, farCenter);
  949. var normal = getPlanesNormal;
  950. //Left plane computation
  951. Cartesian2.Cartesian3.multiplyByScalar(right, l, normal);
  952. Cartesian2.Cartesian3.add(nearCenter, normal, normal);
  953. Cartesian2.Cartesian3.subtract(normal, position, normal);
  954. Cartesian2.Cartesian3.normalize(normal, normal);
  955. Cartesian2.Cartesian3.cross(normal, up, normal);
  956. Cartesian2.Cartesian3.normalize(normal, normal);
  957. var plane = planes[0];
  958. if (!defined.defined(plane)) {
  959. plane = planes[0] = new Transforms.Cartesian4();
  960. }
  961. plane.x = normal.x;
  962. plane.y = normal.y;
  963. plane.z = normal.z;
  964. plane.w = -Cartesian2.Cartesian3.dot(normal, position);
  965. //Right plane computation
  966. Cartesian2.Cartesian3.multiplyByScalar(right, r, normal);
  967. Cartesian2.Cartesian3.add(nearCenter, normal, normal);
  968. Cartesian2.Cartesian3.subtract(normal, position, normal);
  969. Cartesian2.Cartesian3.cross(up, normal, normal);
  970. Cartesian2.Cartesian3.normalize(normal, normal);
  971. plane = planes[1];
  972. if (!defined.defined(plane)) {
  973. plane = planes[1] = new Transforms.Cartesian4();
  974. }
  975. plane.x = normal.x;
  976. plane.y = normal.y;
  977. plane.z = normal.z;
  978. plane.w = -Cartesian2.Cartesian3.dot(normal, position);
  979. //Bottom plane computation
  980. Cartesian2.Cartesian3.multiplyByScalar(up, b, normal);
  981. Cartesian2.Cartesian3.add(nearCenter, normal, normal);
  982. Cartesian2.Cartesian3.subtract(normal, position, normal);
  983. Cartesian2.Cartesian3.cross(right, normal, normal);
  984. Cartesian2.Cartesian3.normalize(normal, normal);
  985. plane = planes[2];
  986. if (!defined.defined(plane)) {
  987. plane = planes[2] = new Transforms.Cartesian4();
  988. }
  989. plane.x = normal.x;
  990. plane.y = normal.y;
  991. plane.z = normal.z;
  992. plane.w = -Cartesian2.Cartesian3.dot(normal, position);
  993. //Top plane computation
  994. Cartesian2.Cartesian3.multiplyByScalar(up, t, normal);
  995. Cartesian2.Cartesian3.add(nearCenter, normal, normal);
  996. Cartesian2.Cartesian3.subtract(normal, position, normal);
  997. Cartesian2.Cartesian3.cross(normal, right, normal);
  998. Cartesian2.Cartesian3.normalize(normal, normal);
  999. plane = planes[3];
  1000. if (!defined.defined(plane)) {
  1001. plane = planes[3] = new Transforms.Cartesian4();
  1002. }
  1003. plane.x = normal.x;
  1004. plane.y = normal.y;
  1005. plane.z = normal.z;
  1006. plane.w = -Cartesian2.Cartesian3.dot(normal, position);
  1007. //Near plane computation
  1008. plane = planes[4];
  1009. if (!defined.defined(plane)) {
  1010. plane = planes[4] = new Transforms.Cartesian4();
  1011. }
  1012. plane.x = direction.x;
  1013. plane.y = direction.y;
  1014. plane.z = direction.z;
  1015. plane.w = -Cartesian2.Cartesian3.dot(direction, nearCenter);
  1016. //Far plane computation
  1017. Cartesian2.Cartesian3.negate(direction, normal);
  1018. plane = planes[5];
  1019. if (!defined.defined(plane)) {
  1020. plane = planes[5] = new Transforms.Cartesian4();
  1021. }
  1022. plane.x = normal.x;
  1023. plane.y = normal.y;
  1024. plane.z = normal.z;
  1025. plane.w = -Cartesian2.Cartesian3.dot(normal, farCenter);
  1026. return this._cullingVolume;
  1027. };
  1028. /**
  1029. * Returns the pixel's width and height in meters.
  1030. *
  1031. * @param {Number} drawingBufferWidth The width of the drawing buffer.
  1032. * @param {Number} drawingBufferHeight The height of the drawing buffer.
  1033. * @param {Number} distance The distance to the near plane in meters.
  1034. * @param {Number} pixelRatio The scaling factor from pixel space to coordinate space.
  1035. * @param {Cartesian2} result The object onto which to store the result.
  1036. * @returns {Cartesian2} The modified result parameter or a new instance of {@link Cartesian2} with the pixel's width and height in the x and y properties, respectively.
  1037. *
  1038. * @exception {DeveloperError} drawingBufferWidth must be greater than zero.
  1039. * @exception {DeveloperError} drawingBufferHeight must be greater than zero.
  1040. * @exception {DeveloperError} pixelRatio must be greater than zero.
  1041. *
  1042. * @example
  1043. * // Example 1
  1044. * // Get the width and height of a pixel.
  1045. * var pixelSize = camera.frustum.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, 1.0, scene.pixelRatio, new Cesium.Cartesian2());
  1046. *
  1047. * @example
  1048. * // Example 2
  1049. * // Get the width and height of a pixel if the near plane was set to 'distance'.
  1050. * // For example, get the size of a pixel of an image on a billboard.
  1051. * var position = camera.position;
  1052. * var direction = camera.direction;
  1053. * var toCenter = Cesium.Cartesian3.subtract(primitive.boundingVolume.center, position, new Cesium.Cartesian3()); // vector from camera to a primitive
  1054. * var toCenterProj = Cesium.Cartesian3.multiplyByScalar(direction, Cesium.Cartesian3.dot(direction, toCenter), new Cesium.Cartesian3()); // project vector onto camera direction vector
  1055. * var distance = Cesium.Cartesian3.magnitude(toCenterProj);
  1056. * var pixelSize = camera.frustum.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, distance, scene.pixelRatio, new Cesium.Cartesian2());
  1057. */
  1058. PerspectiveOffCenterFrustum.prototype.getPixelDimensions = function(drawingBufferWidth, drawingBufferHeight, distance, pixelRatio, result) {
  1059. update$2(this);
  1060. if (pixelRatio instanceof Cartesian2.Cartesian2) {
  1061. result = pixelRatio;
  1062. pixelRatio = 1.0;
  1063. Transforms.deprecationWarning('getPixelDimensions-parameter-change', 'getPixelDimensions now takes a pixelRatio argument before the result argument in Cesium 1.63. The previous function definition will no longer work in 1.65.');
  1064. }
  1065. //>>includeStart('debug', pragmas.debug);
  1066. if (!defined.defined(drawingBufferWidth) || !defined.defined(drawingBufferHeight)) {
  1067. throw new Check.DeveloperError('Both drawingBufferWidth and drawingBufferHeight are required.');
  1068. }
  1069. if (drawingBufferWidth <= 0) {
  1070. throw new Check.DeveloperError('drawingBufferWidth must be greater than zero.');
  1071. }
  1072. if (drawingBufferHeight <= 0) {
  1073. throw new Check.DeveloperError('drawingBufferHeight must be greater than zero.');
  1074. }
  1075. if (!defined.defined(distance)) {
  1076. throw new Check.DeveloperError('distance is required.');
  1077. }
  1078. if (!defined.defined(pixelRatio)) {
  1079. throw new Check.DeveloperError('pixelRatio is required');
  1080. }
  1081. if (pixelRatio <= 0) {
  1082. throw new Check.DeveloperError('pixelRatio must be greater than zero.');
  1083. }
  1084. if (!defined.defined(result)) {
  1085. throw new Check.DeveloperError('A result object is required.');
  1086. }
  1087. //>>includeEnd('debug');
  1088. var inverseNear = 1.0 / this.near;
  1089. var tanTheta = this.top * inverseNear;
  1090. var pixelHeight = 2.0 * pixelRatio * distance * tanTheta / drawingBufferHeight;
  1091. tanTheta = this.right * inverseNear;
  1092. var pixelWidth = 2.0 * pixelRatio * distance * tanTheta / drawingBufferWidth;
  1093. result.x = pixelWidth;
  1094. result.y = pixelHeight;
  1095. return result;
  1096. };
  1097. /**
  1098. * Returns a duplicate of a PerspectiveOffCenterFrustum instance.
  1099. *
  1100. * @param {PerspectiveOffCenterFrustum} [result] The object onto which to store the result.
  1101. * @returns {PerspectiveOffCenterFrustum} The modified result parameter or a new PerspectiveFrustum instance if one was not provided.
  1102. */
  1103. PerspectiveOffCenterFrustum.prototype.clone = function(result) {
  1104. if (!defined.defined(result)) {
  1105. result = new PerspectiveOffCenterFrustum();
  1106. }
  1107. result.right = this.right;
  1108. result.left = this.left;
  1109. result.top = this.top;
  1110. result.bottom = this.bottom;
  1111. result.near = this.near;
  1112. result.far = this.far;
  1113. // force update of clone to compute matrices
  1114. result._left = undefined;
  1115. result._right = undefined;
  1116. result._top = undefined;
  1117. result._bottom = undefined;
  1118. result._near = undefined;
  1119. result._far = undefined;
  1120. return result;
  1121. };
  1122. /**
  1123. * Compares the provided PerspectiveOffCenterFrustum componentwise and returns
  1124. * <code>true</code> if they are equal, <code>false</code> otherwise.
  1125. *
  1126. * @param {PerspectiveOffCenterFrustum} [other] The right hand side PerspectiveOffCenterFrustum.
  1127. * @returns {Boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
  1128. */
  1129. PerspectiveOffCenterFrustum.prototype.equals = function(other) {
  1130. return (defined.defined(other) && other instanceof PerspectiveOffCenterFrustum &&
  1131. this.right === other.right &&
  1132. this.left === other.left &&
  1133. this.top === other.top &&
  1134. this.bottom === other.bottom &&
  1135. this.near === other.near &&
  1136. this.far === other.far);
  1137. };
  1138. /**
  1139. * Compares the provided PerspectiveOffCenterFrustum componentwise and returns
  1140. * <code>true</code> if they pass an absolute or relative tolerance test,
  1141. * <code>false</code> otherwise.
  1142. *
  1143. * @param {PerspectiveOffCenterFrustum} other The right hand side PerspectiveOffCenterFrustum.
  1144. * @param {Number} relativeEpsilon The relative epsilon tolerance to use for equality testing.
  1145. * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.
  1146. * @returns {Boolean} <code>true</code> if this and other are within the provided epsilon, <code>false</code> otherwise.
  1147. */
  1148. PerspectiveOffCenterFrustum.prototype.equalsEpsilon = function(other, relativeEpsilon, absoluteEpsilon) {
  1149. return (other === this) ||
  1150. (defined.defined(other) &&
  1151. other instanceof PerspectiveOffCenterFrustum &&
  1152. _Math.CesiumMath.equalsEpsilon(this.right, other.right, relativeEpsilon, absoluteEpsilon) &&
  1153. _Math.CesiumMath.equalsEpsilon(this.left, other.left, relativeEpsilon, absoluteEpsilon) &&
  1154. _Math.CesiumMath.equalsEpsilon(this.top, other.top, relativeEpsilon, absoluteEpsilon) &&
  1155. _Math.CesiumMath.equalsEpsilon(this.bottom, other.bottom, relativeEpsilon, absoluteEpsilon) &&
  1156. _Math.CesiumMath.equalsEpsilon(this.near, other.near, relativeEpsilon, absoluteEpsilon) &&
  1157. _Math.CesiumMath.equalsEpsilon(this.far, other.far, relativeEpsilon, absoluteEpsilon));
  1158. };
  1159. /**
  1160. * The viewing frustum is defined by 6 planes.
  1161. * Each plane is represented by a {@link Cartesian4} object, where the x, y, and z components
  1162. * define the unit vector normal to the plane, and the w component is the distance of the
  1163. * plane from the origin/camera position.
  1164. *
  1165. * @alias PerspectiveFrustum
  1166. * @constructor
  1167. *
  1168. * @param {Object} [options] An object with the following properties:
  1169. * @param {Number} [options.fov] The angle of the field of view (FOV), in radians.
  1170. * @param {Number} [options.aspectRatio] The aspect ratio of the frustum's width to it's height.
  1171. * @param {Number} [options.near=1.0] The distance of the near plane.
  1172. * @param {Number} [options.far=500000000.0] The distance of the far plane.
  1173. * @param {Number} [options.xOffset=0.0] The offset in the x direction.
  1174. * @param {Number} [options.yOffset=0.0] The offset in the y direction.
  1175. *
  1176. * @example
  1177. * var frustum = new Cesium.PerspectiveFrustum({
  1178. * fov : Cesium.Math.PI_OVER_THREE,
  1179. * aspectRatio : canvas.clientWidth / canvas.clientHeight
  1180. * near : 1.0,
  1181. * far : 1000.0
  1182. * });
  1183. *
  1184. * @see PerspectiveOffCenterFrustum
  1185. */
  1186. function PerspectiveFrustum(options) {
  1187. options = defaultValue.defaultValue(options, defaultValue.defaultValue.EMPTY_OBJECT);
  1188. this._offCenterFrustum = new PerspectiveOffCenterFrustum();
  1189. /**
  1190. * The angle of the field of view (FOV), in radians. This angle will be used
  1191. * as the horizontal FOV if the width is greater than the height, otherwise
  1192. * it will be the vertical FOV.
  1193. * @type {Number}
  1194. * @default undefined
  1195. */
  1196. this.fov = options.fov;
  1197. this._fov = undefined;
  1198. this._fovy = undefined;
  1199. this._sseDenominator = undefined;
  1200. /**
  1201. * The aspect ratio of the frustum's width to it's height.
  1202. * @type {Number}
  1203. * @default undefined
  1204. */
  1205. this.aspectRatio = options.aspectRatio;
  1206. this._aspectRatio = undefined;
  1207. /**
  1208. * The distance of the near plane.
  1209. * @type {Number}
  1210. * @default 1.0
  1211. */
  1212. this.near = defaultValue.defaultValue(options.near, 1.0);
  1213. this._near = this.near;
  1214. /**
  1215. * The distance of the far plane.
  1216. * @type {Number}
  1217. * @default 500000000.0
  1218. */
  1219. this.far = defaultValue.defaultValue(options.far, 500000000.0);
  1220. this._far = this.far;
  1221. /**
  1222. * Offsets the frustum in the x direction.
  1223. * @type {Number}
  1224. * @default 0.0
  1225. */
  1226. this.xOffset = defaultValue.defaultValue(options.xOffset, 0.0);
  1227. this._xOffset = this.xOffset;
  1228. /**
  1229. * Offsets the frustum in the y direction.
  1230. * @type {Number}
  1231. * @default 0.0
  1232. */
  1233. this.yOffset = defaultValue.defaultValue(options.yOffset, 0.0);
  1234. this._yOffset = this.yOffset;
  1235. }
  1236. /**
  1237. * The number of elements used to pack the object into an array.
  1238. * @type {Number}
  1239. */
  1240. PerspectiveFrustum.packedLength = 6;
  1241. /**
  1242. * Stores the provided instance into the provided array.
  1243. *
  1244. * @param {PerspectiveFrustum} value The value to pack.
  1245. * @param {Number[]} array The array to pack into.
  1246. * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.
  1247. *
  1248. * @returns {Number[]} The array that was packed into
  1249. */
  1250. PerspectiveFrustum.pack = function(value, array, startingIndex) {
  1251. //>>includeStart('debug', pragmas.debug);
  1252. Check.Check.typeOf.object('value', value);
  1253. Check.Check.defined('array', array);
  1254. //>>includeEnd('debug');
  1255. startingIndex = defaultValue.defaultValue(startingIndex, 0);
  1256. array[startingIndex++] = value.fov;
  1257. array[startingIndex++] = value.aspectRatio;
  1258. array[startingIndex++] = value.near;
  1259. array[startingIndex++] = value.far;
  1260. array[startingIndex++] = value.xOffset;
  1261. array[startingIndex] = value.yOffset;
  1262. return array;
  1263. };
  1264. /**
  1265. * Retrieves an instance from a packed array.
  1266. *
  1267. * @param {Number[]} array The packed array.
  1268. * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.
  1269. * @param {PerspectiveFrustum} [result] The object into which to store the result.
  1270. * @returns {PerspectiveFrustum} The modified result parameter or a new PerspectiveFrustum instance if one was not provided.
  1271. */
  1272. PerspectiveFrustum.unpack = function(array, startingIndex, result) {
  1273. //>>includeStart('debug', pragmas.debug);
  1274. Check.Check.defined('array', array);
  1275. //>>includeEnd('debug');
  1276. startingIndex = defaultValue.defaultValue(startingIndex, 0);
  1277. if (!defined.defined(result)) {
  1278. result = new PerspectiveFrustum();
  1279. }
  1280. result.fov = array[startingIndex++];
  1281. result.aspectRatio = array[startingIndex++];
  1282. result.near = array[startingIndex++];
  1283. result.far = array[startingIndex++];
  1284. result.xOffset = array[startingIndex++];
  1285. result.yOffset = array[startingIndex];
  1286. return result;
  1287. };
  1288. function update$3(frustum) {
  1289. //>>includeStart('debug', pragmas.debug);
  1290. if (!defined.defined(frustum.fov) || !defined.defined(frustum.aspectRatio) || !defined.defined(frustum.near) || !defined.defined(frustum.far)) {
  1291. throw new Check.DeveloperError('fov, aspectRatio, near, or far parameters are not set.');
  1292. }
  1293. //>>includeEnd('debug');
  1294. var f = frustum._offCenterFrustum;
  1295. if (frustum.fov !== frustum._fov || frustum.aspectRatio !== frustum._aspectRatio ||
  1296. frustum.near !== frustum._near || frustum.far !== frustum._far ||
  1297. frustum.xOffset !== frustum._xOffset || frustum.yOffset !== frustum._yOffset) {
  1298. //>>includeStart('debug', pragmas.debug);
  1299. if (frustum.fov < 0 || frustum.fov >= Math.PI) {
  1300. throw new Check.DeveloperError('fov must be in the range [0, PI).');
  1301. }
  1302. if (frustum.aspectRatio < 0) {
  1303. throw new Check.DeveloperError('aspectRatio must be positive.');
  1304. }
  1305. if (frustum.near < 0 || frustum.near > frustum.far) {
  1306. throw new Check.DeveloperError('near must be greater than zero and less than far.');
  1307. }
  1308. //>>includeEnd('debug');
  1309. frustum._aspectRatio = frustum.aspectRatio;
  1310. frustum._fov = frustum.fov;
  1311. frustum._fovy = (frustum.aspectRatio <= 1) ? frustum.fov : Math.atan(Math.tan(frustum.fov * 0.5) / frustum.aspectRatio) * 2.0;
  1312. frustum._near = frustum.near;
  1313. frustum._far = frustum.far;
  1314. frustum._sseDenominator = 2.0 * Math.tan(0.5 * frustum._fovy);
  1315. frustum._xOffset = frustum.xOffset;
  1316. frustum._yOffset = frustum.yOffset;
  1317. f.top = frustum.near * Math.tan(0.5 * frustum._fovy);
  1318. f.bottom = -f.top;
  1319. f.right = frustum.aspectRatio * f.top;
  1320. f.left = -f.right;
  1321. f.near = frustum.near;
  1322. f.far = frustum.far;
  1323. f.right += frustum.xOffset;
  1324. f.left += frustum.xOffset;
  1325. f.top += frustum.yOffset;
  1326. f.bottom += frustum.yOffset;
  1327. }
  1328. }
  1329. defineProperties.defineProperties(PerspectiveFrustum.prototype, {
  1330. /**
  1331. * Gets the perspective projection matrix computed from the view frustum.
  1332. * @memberof PerspectiveFrustum.prototype
  1333. * @type {Matrix4}
  1334. * @readonly
  1335. *
  1336. * @see PerspectiveFrustum#infiniteProjectionMatrix
  1337. */
  1338. projectionMatrix : {
  1339. get : function() {
  1340. update$3(this);
  1341. return this._offCenterFrustum.projectionMatrix;
  1342. }
  1343. },
  1344. /**
  1345. * The perspective projection matrix computed from the view frustum with an infinite far plane.
  1346. * @memberof PerspectiveFrustum.prototype
  1347. * @type {Matrix4}
  1348. * @readonly
  1349. *
  1350. * @see PerspectiveFrustum#projectionMatrix
  1351. */
  1352. infiniteProjectionMatrix : {
  1353. get : function() {
  1354. update$3(this);
  1355. return this._offCenterFrustum.infiniteProjectionMatrix;
  1356. }
  1357. },
  1358. /**
  1359. * Gets the angle of the vertical field of view, in radians.
  1360. * @memberof PerspectiveFrustum.prototype
  1361. * @type {Number}
  1362. * @readonly
  1363. * @default undefined
  1364. */
  1365. fovy : {
  1366. get : function() {
  1367. update$3(this);
  1368. return this._fovy;
  1369. }
  1370. },
  1371. /**
  1372. * @readonly
  1373. * @private
  1374. */
  1375. sseDenominator : {
  1376. get : function () {
  1377. update$3(this);
  1378. return this._sseDenominator;
  1379. }
  1380. }
  1381. });
  1382. /**
  1383. * Creates a culling volume for this frustum.
  1384. *
  1385. * @param {Cartesian3} position The eye position.
  1386. * @param {Cartesian3} direction The view direction.
  1387. * @param {Cartesian3} up The up direction.
  1388. * @returns {CullingVolume} A culling volume at the given position and orientation.
  1389. *
  1390. * @example
  1391. * // Check if a bounding volume intersects the frustum.
  1392. * var cullingVolume = frustum.computeCullingVolume(cameraPosition, cameraDirection, cameraUp);
  1393. * var intersect = cullingVolume.computeVisibility(boundingVolume);
  1394. */
  1395. PerspectiveFrustum.prototype.computeCullingVolume = function(position, direction, up) {
  1396. update$3(this);
  1397. return this._offCenterFrustum.computeCullingVolume(position, direction, up);
  1398. };
  1399. /**
  1400. * Returns the pixel's width and height in meters.
  1401. *
  1402. * @param {Number} drawingBufferWidth The width of the drawing buffer.
  1403. * @param {Number} drawingBufferHeight The height of the drawing buffer.
  1404. * @param {Number} distance The distance to the near plane in meters.
  1405. * @param {Number} pixelRatio The scaling factor from pixel space to coordinate space.
  1406. * @param {Cartesian2} result The object onto which to store the result.
  1407. * @returns {Cartesian2} The modified result parameter or a new instance of {@link Cartesian2} with the pixel's width and height in the x and y properties, respectively.
  1408. *
  1409. * @exception {DeveloperError} drawingBufferWidth must be greater than zero.
  1410. * @exception {DeveloperError} drawingBufferHeight must be greater than zero.
  1411. * @exception {DeveloperError} pixelRatio must be greater than zero.
  1412. *
  1413. * @example
  1414. * // Example 1
  1415. * // Get the width and height of a pixel.
  1416. * var pixelSize = camera.frustum.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, 1.0, scene.pixelRatio, new Cesium.Cartesian2());
  1417. *
  1418. * @example
  1419. * // Example 2
  1420. * // Get the width and height of a pixel if the near plane was set to 'distance'.
  1421. * // For example, get the size of a pixel of an image on a billboard.
  1422. * var position = camera.position;
  1423. * var direction = camera.direction;
  1424. * var toCenter = Cesium.Cartesian3.subtract(primitive.boundingVolume.center, position, new Cesium.Cartesian3()); // vector from camera to a primitive
  1425. * var toCenterProj = Cesium.Cartesian3.multiplyByScalar(direction, Cesium.Cartesian3.dot(direction, toCenter), new Cesium.Cartesian3()); // project vector onto camera direction vector
  1426. * var distance = Cesium.Cartesian3.magnitude(toCenterProj);
  1427. * var pixelSize = camera.frustum.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, distance, scene.pixelRatio, new Cesium.Cartesian2());
  1428. */
  1429. PerspectiveFrustum.prototype.getPixelDimensions = function(drawingBufferWidth, drawingBufferHeight, distance, pixelRatio, result) {
  1430. update$3(this);
  1431. if (pixelRatio instanceof Cartesian2.Cartesian2) {
  1432. result = pixelRatio;
  1433. pixelRatio = 1.0;
  1434. Transforms.deprecationWarning('getPixelDimensions-parameter-change', 'getPixelDimensions now takes a pixelRatio argument before the result argument in Cesium 1.63. The previous function definition will no longer work in 1.65.');
  1435. }
  1436. return this._offCenterFrustum.getPixelDimensions(drawingBufferWidth, drawingBufferHeight, distance, pixelRatio, result);
  1437. };
  1438. /**
  1439. * Returns a duplicate of a PerspectiveFrustum instance.
  1440. *
  1441. * @param {PerspectiveFrustum} [result] The object onto which to store the result.
  1442. * @returns {PerspectiveFrustum} The modified result parameter or a new PerspectiveFrustum instance if one was not provided.
  1443. */
  1444. PerspectiveFrustum.prototype.clone = function(result) {
  1445. if (!defined.defined(result)) {
  1446. result = new PerspectiveFrustum();
  1447. }
  1448. result.aspectRatio = this.aspectRatio;
  1449. result.fov = this.fov;
  1450. result.near = this.near;
  1451. result.far = this.far;
  1452. // force update of clone to compute matrices
  1453. result._aspectRatio = undefined;
  1454. result._fov = undefined;
  1455. result._near = undefined;
  1456. result._far = undefined;
  1457. this._offCenterFrustum.clone(result._offCenterFrustum);
  1458. return result;
  1459. };
  1460. /**
  1461. * Compares the provided PerspectiveFrustum componentwise and returns
  1462. * <code>true</code> if they are equal, <code>false</code> otherwise.
  1463. *
  1464. * @param {PerspectiveFrustum} [other] The right hand side PerspectiveFrustum.
  1465. * @returns {Boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
  1466. */
  1467. PerspectiveFrustum.prototype.equals = function(other) {
  1468. if (!defined.defined(other) || !(other instanceof PerspectiveFrustum)) {
  1469. return false;
  1470. }
  1471. update$3(this);
  1472. update$3(other);
  1473. return (this.fov === other.fov &&
  1474. this.aspectRatio === other.aspectRatio &&
  1475. this._offCenterFrustum.equals(other._offCenterFrustum));
  1476. };
  1477. /**
  1478. * Compares the provided PerspectiveFrustum componentwise and returns
  1479. * <code>true</code> if they pass an absolute or relative tolerance test,
  1480. * <code>false</code> otherwise.
  1481. *
  1482. * @param {PerspectiveFrustum} other The right hand side PerspectiveFrustum.
  1483. * @param {Number} relativeEpsilon The relative epsilon tolerance to use for equality testing.
  1484. * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.
  1485. * @returns {Boolean} <code>true</code> if this and other are within the provided epsilon, <code>false</code> otherwise.
  1486. */
  1487. PerspectiveFrustum.prototype.equalsEpsilon = function(other, relativeEpsilon, absoluteEpsilon) {
  1488. if (!defined.defined(other) || !(other instanceof PerspectiveFrustum)) {
  1489. return false;
  1490. }
  1491. update$3(this);
  1492. update$3(other);
  1493. return (_Math.CesiumMath.equalsEpsilon(this.fov, other.fov, relativeEpsilon, absoluteEpsilon) &&
  1494. _Math.CesiumMath.equalsEpsilon(this.aspectRatio, other.aspectRatio, relativeEpsilon, absoluteEpsilon) &&
  1495. this._offCenterFrustum.equalsEpsilon(other._offCenterFrustum, relativeEpsilon, absoluteEpsilon));
  1496. };
  1497. var PERSPECTIVE = 0;
  1498. var ORTHOGRAPHIC = 1;
  1499. /**
  1500. * Describes a frustum at the given the origin and orientation.
  1501. *
  1502. * @alias FrustumGeometry
  1503. * @constructor
  1504. *
  1505. * @param {Object} options Object with the following properties:
  1506. * @param {PerspectiveFrustum|OrthographicFrustum} options.frustum The frustum.
  1507. * @param {Cartesian3} options.origin The origin of the frustum.
  1508. * @param {Quaternion} options.orientation The orientation of the frustum.
  1509. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.
  1510. */
  1511. function FrustumGeometry(options) {
  1512. //>>includeStart('debug', pragmas.debug);
  1513. Check.Check.typeOf.object('options', options);
  1514. Check.Check.typeOf.object('options.frustum', options.frustum);
  1515. Check.Check.typeOf.object('options.origin', options.origin);
  1516. Check.Check.typeOf.object('options.orientation', options.orientation);
  1517. //>>includeEnd('debug');
  1518. var frustum = options.frustum;
  1519. var orientation = options.orientation;
  1520. var origin = options.origin;
  1521. var vertexFormat = defaultValue.defaultValue(options.vertexFormat, VertexFormat.VertexFormat.DEFAULT);
  1522. // This is private because it is used by DebugCameraPrimitive to draw a multi-frustum by
  1523. // creating multiple FrustumGeometrys. This way the near plane of one frustum doesn't overlap
  1524. // the far plane of another.
  1525. var drawNearPlane = defaultValue.defaultValue(options._drawNearPlane, true);
  1526. var frustumType;
  1527. var frustumPackedLength;
  1528. if (frustum instanceof PerspectiveFrustum) {
  1529. frustumType = PERSPECTIVE;
  1530. frustumPackedLength = PerspectiveFrustum.packedLength;
  1531. } else if (frustum instanceof OrthographicFrustum) {
  1532. frustumType = ORTHOGRAPHIC;
  1533. frustumPackedLength = OrthographicFrustum.packedLength;
  1534. }
  1535. this._frustumType = frustumType;
  1536. this._frustum = frustum.clone();
  1537. this._origin = Cartesian2.Cartesian3.clone(origin);
  1538. this._orientation = Transforms.Quaternion.clone(orientation);
  1539. this._drawNearPlane = drawNearPlane;
  1540. this._vertexFormat = vertexFormat;
  1541. this._workerName = 'createFrustumGeometry';
  1542. /**
  1543. * The number of elements used to pack the object into an array.
  1544. * @type {Number}
  1545. */
  1546. this.packedLength = 2 + frustumPackedLength + Cartesian2.Cartesian3.packedLength + Transforms.Quaternion.packedLength + VertexFormat.VertexFormat.packedLength;
  1547. }
  1548. /**
  1549. * Stores the provided instance into the provided array.
  1550. *
  1551. * @param {FrustumGeometry} value The value to pack.
  1552. * @param {Number[]} array The array to pack into.
  1553. * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.
  1554. *
  1555. * @returns {Number[]} The array that was packed into
  1556. */
  1557. FrustumGeometry.pack = function(value, array, startingIndex) {
  1558. //>>includeStart('debug', pragmas.debug);
  1559. Check.Check.typeOf.object('value', value);
  1560. Check.Check.defined('array', array);
  1561. //>>includeEnd('debug');
  1562. startingIndex = defaultValue.defaultValue(startingIndex, 0);
  1563. var frustumType = value._frustumType;
  1564. var frustum = value._frustum;
  1565. array[startingIndex++] = frustumType;
  1566. if (frustumType === PERSPECTIVE) {
  1567. PerspectiveFrustum.pack(frustum, array, startingIndex);
  1568. startingIndex += PerspectiveFrustum.packedLength;
  1569. } else {
  1570. OrthographicFrustum.pack(frustum, array, startingIndex);
  1571. startingIndex += OrthographicFrustum.packedLength;
  1572. }
  1573. Cartesian2.Cartesian3.pack(value._origin, array, startingIndex);
  1574. startingIndex += Cartesian2.Cartesian3.packedLength;
  1575. Transforms.Quaternion.pack(value._orientation, array, startingIndex);
  1576. startingIndex += Transforms.Quaternion.packedLength;
  1577. VertexFormat.VertexFormat.pack(value._vertexFormat, array, startingIndex);
  1578. startingIndex += VertexFormat.VertexFormat.packedLength;
  1579. array[startingIndex] = value._drawNearPlane ? 1.0 : 0.0;
  1580. return array;
  1581. };
  1582. var scratchPackPerspective = new PerspectiveFrustum();
  1583. var scratchPackOrthographic = new OrthographicFrustum();
  1584. var scratchPackQuaternion = new Transforms.Quaternion();
  1585. var scratchPackorigin = new Cartesian2.Cartesian3();
  1586. var scratchVertexFormat = new VertexFormat.VertexFormat();
  1587. /**
  1588. * Retrieves an instance from a packed array.
  1589. *
  1590. * @param {Number[]} array The packed array.
  1591. * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.
  1592. * @param {FrustumGeometry} [result] The object into which to store the result.
  1593. */
  1594. FrustumGeometry.unpack = function(array, startingIndex, result) {
  1595. //>>includeStart('debug', pragmas.debug);
  1596. Check.Check.defined('array', array);
  1597. //>>includeEnd('debug');
  1598. startingIndex = defaultValue.defaultValue(startingIndex, 0);
  1599. var frustumType = array[startingIndex++];
  1600. var frustum;
  1601. if (frustumType === PERSPECTIVE) {
  1602. frustum = PerspectiveFrustum.unpack(array, startingIndex, scratchPackPerspective);
  1603. startingIndex += PerspectiveFrustum.packedLength;
  1604. } else {
  1605. frustum = OrthographicFrustum.unpack(array, startingIndex, scratchPackOrthographic);
  1606. startingIndex += OrthographicFrustum.packedLength;
  1607. }
  1608. var origin = Cartesian2.Cartesian3.unpack(array, startingIndex, scratchPackorigin);
  1609. startingIndex += Cartesian2.Cartesian3.packedLength;
  1610. var orientation = Transforms.Quaternion.unpack(array, startingIndex, scratchPackQuaternion);
  1611. startingIndex += Transforms.Quaternion.packedLength;
  1612. var vertexFormat = VertexFormat.VertexFormat.unpack(array, startingIndex, scratchVertexFormat);
  1613. startingIndex += VertexFormat.VertexFormat.packedLength;
  1614. var drawNearPlane = array[startingIndex] === 1.0;
  1615. if (!defined.defined(result)) {
  1616. return new FrustumGeometry({
  1617. frustum : frustum,
  1618. origin : origin,
  1619. orientation : orientation,
  1620. vertexFormat : vertexFormat,
  1621. _drawNearPlane : drawNearPlane
  1622. });
  1623. }
  1624. var frustumResult = frustumType === result._frustumType ? result._frustum : undefined;
  1625. result._frustum = frustum.clone(frustumResult);
  1626. result._frustumType = frustumType;
  1627. result._origin = Cartesian2.Cartesian3.clone(origin, result._origin);
  1628. result._orientation = Transforms.Quaternion.clone(orientation, result._orientation);
  1629. result._vertexFormat = VertexFormat.VertexFormat.clone(vertexFormat, result._vertexFormat);
  1630. result._drawNearPlane = drawNearPlane;
  1631. return result;
  1632. };
  1633. function getAttributes(offset, normals, tangents, bitangents, st, normal, tangent, bitangent) {
  1634. var stOffset = offset / 3 * 2;
  1635. for (var i = 0; i < 4; ++i) {
  1636. if (defined.defined(normals)) {
  1637. normals[offset] = normal.x;
  1638. normals[offset + 1] = normal.y;
  1639. normals[offset + 2] = normal.z;
  1640. }
  1641. if (defined.defined(tangents)) {
  1642. tangents[offset] = tangent.x;
  1643. tangents[offset + 1] = tangent.y;
  1644. tangents[offset + 2] = tangent.z;
  1645. }
  1646. if (defined.defined(bitangents)) {
  1647. bitangents[offset] = bitangent.x;
  1648. bitangents[offset + 1] = bitangent.y;
  1649. bitangents[offset + 2] = bitangent.z;
  1650. }
  1651. offset += 3;
  1652. }
  1653. st[stOffset] = 0.0;
  1654. st[stOffset + 1] = 0.0;
  1655. st[stOffset + 2] = 1.0;
  1656. st[stOffset + 3] = 0.0;
  1657. st[stOffset + 4] = 1.0;
  1658. st[stOffset + 5] = 1.0;
  1659. st[stOffset + 6] = 0.0;
  1660. st[stOffset + 7] = 1.0;
  1661. }
  1662. var scratchRotationMatrix = new Transforms.Matrix3();
  1663. var scratchViewMatrix = new Transforms.Matrix4();
  1664. var scratchInverseMatrix = new Transforms.Matrix4();
  1665. var scratchXDirection = new Cartesian2.Cartesian3();
  1666. var scratchYDirection = new Cartesian2.Cartesian3();
  1667. var scratchZDirection = new Cartesian2.Cartesian3();
  1668. var scratchNegativeX = new Cartesian2.Cartesian3();
  1669. var scratchNegativeY = new Cartesian2.Cartesian3();
  1670. var scratchNegativeZ = new Cartesian2.Cartesian3();
  1671. var frustumSplits = new Array(3);
  1672. var frustumCornersNDC = new Array(4);
  1673. frustumCornersNDC[0] = new Transforms.Cartesian4(-1.0, -1.0, 1.0, 1.0);
  1674. frustumCornersNDC[1] = new Transforms.Cartesian4(1.0, -1.0, 1.0, 1.0);
  1675. frustumCornersNDC[2] = new Transforms.Cartesian4(1.0, 1.0, 1.0, 1.0);
  1676. frustumCornersNDC[3] = new Transforms.Cartesian4(-1.0, 1.0, 1.0, 1.0);
  1677. var scratchFrustumCorners = new Array(4);
  1678. for (var i = 0; i < 4; ++i) {
  1679. scratchFrustumCorners[i] = new Transforms.Cartesian4();
  1680. }
  1681. FrustumGeometry._computeNearFarPlanes = function(origin, orientation, frustumType, frustum, positions, xDirection, yDirection, zDirection) {
  1682. var rotationMatrix = Transforms.Matrix3.fromQuaternion(orientation, scratchRotationMatrix);
  1683. var x = defaultValue.defaultValue(xDirection, scratchXDirection);
  1684. var y = defaultValue.defaultValue(yDirection, scratchYDirection);
  1685. var z = defaultValue.defaultValue(zDirection, scratchZDirection);
  1686. x = Transforms.Matrix3.getColumn(rotationMatrix, 0, x);
  1687. y = Transforms.Matrix3.getColumn(rotationMatrix, 1, y);
  1688. z = Transforms.Matrix3.getColumn(rotationMatrix, 2, z);
  1689. Cartesian2.Cartesian3.normalize(x, x);
  1690. Cartesian2.Cartesian3.normalize(y, y);
  1691. Cartesian2.Cartesian3.normalize(z, z);
  1692. Cartesian2.Cartesian3.negate(x, x);
  1693. var view = Transforms.Matrix4.computeView(origin, z, y, x, scratchViewMatrix);
  1694. var inverseView;
  1695. var inverseViewProjection;
  1696. if (frustumType === PERSPECTIVE) {
  1697. var projection = frustum.projectionMatrix;
  1698. var viewProjection = Transforms.Matrix4.multiply(projection, view, scratchInverseMatrix);
  1699. inverseViewProjection = Transforms.Matrix4.inverse(viewProjection, scratchInverseMatrix);
  1700. } else {
  1701. inverseView = Transforms.Matrix4.inverseTransformation(view, scratchInverseMatrix);
  1702. }
  1703. if (defined.defined(inverseViewProjection)) {
  1704. frustumSplits[0] = frustum.near;
  1705. frustumSplits[1] = frustum.far;
  1706. } else {
  1707. frustumSplits[0] = 0.0;
  1708. frustumSplits[1] = frustum.near;
  1709. frustumSplits[2] = frustum.far;
  1710. }
  1711. for (var i = 0; i < 2; ++i) {
  1712. for (var j = 0; j < 4; ++j) {
  1713. var corner = Transforms.Cartesian4.clone(frustumCornersNDC[j], scratchFrustumCorners[j]);
  1714. if (!defined.defined(inverseViewProjection)) {
  1715. if (defined.defined(frustum._offCenterFrustum)) {
  1716. frustum = frustum._offCenterFrustum;
  1717. }
  1718. var near = frustumSplits[i];
  1719. var far = frustumSplits[i + 1];
  1720. corner.x = (corner.x * (frustum.right - frustum.left) + frustum.left + frustum.right) * 0.5;
  1721. corner.y = (corner.y * (frustum.top - frustum.bottom) + frustum.bottom + frustum.top) * 0.5;
  1722. corner.z = (corner.z * (near - far) - near - far) * 0.5;
  1723. corner.w = 1.0;
  1724. Transforms.Matrix4.multiplyByVector(inverseView, corner, corner);
  1725. } else {
  1726. corner = Transforms.Matrix4.multiplyByVector(inverseViewProjection, corner, corner);
  1727. // Reverse perspective divide
  1728. var w = 1.0 / corner.w;
  1729. Cartesian2.Cartesian3.multiplyByScalar(corner, w, corner);
  1730. Cartesian2.Cartesian3.subtract(corner, origin, corner);
  1731. Cartesian2.Cartesian3.normalize(corner, corner);
  1732. var fac = Cartesian2.Cartesian3.dot(z, corner);
  1733. Cartesian2.Cartesian3.multiplyByScalar(corner, frustumSplits[i] / fac, corner);
  1734. Cartesian2.Cartesian3.add(corner, origin, corner);
  1735. }
  1736. positions[12 * i + j * 3] = corner.x;
  1737. positions[12 * i + j * 3 + 1] = corner.y;
  1738. positions[12 * i + j * 3 + 2] = corner.z;
  1739. }
  1740. }
  1741. };
  1742. /**
  1743. * Computes the geometric representation of a frustum, including its vertices, indices, and a bounding sphere.
  1744. *
  1745. * @param {FrustumGeometry} frustumGeometry A description of the frustum.
  1746. * @returns {Geometry|undefined} The computed vertices and indices.
  1747. */
  1748. FrustumGeometry.createGeometry = function(frustumGeometry) {
  1749. var frustumType = frustumGeometry._frustumType;
  1750. var frustum = frustumGeometry._frustum;
  1751. var origin = frustumGeometry._origin;
  1752. var orientation = frustumGeometry._orientation;
  1753. var drawNearPlane = frustumGeometry._drawNearPlane;
  1754. var vertexFormat = frustumGeometry._vertexFormat;
  1755. var numberOfPlanes = drawNearPlane ? 6 : 5;
  1756. var positions = new Float64Array(3 * 4 * 6);
  1757. FrustumGeometry._computeNearFarPlanes(origin, orientation, frustumType, frustum, positions);
  1758. // -x plane
  1759. var offset = 3 * 4 * 2;
  1760. positions[offset] = positions[3 * 4];
  1761. positions[offset + 1] = positions[3 * 4 + 1];
  1762. positions[offset + 2] = positions[3 * 4 + 2];
  1763. positions[offset + 3] = positions[0];
  1764. positions[offset + 4] = positions[1];
  1765. positions[offset + 5] = positions[2];
  1766. positions[offset + 6] = positions[3 * 3];
  1767. positions[offset + 7] = positions[3 * 3 + 1];
  1768. positions[offset + 8] = positions[3 * 3 + 2];
  1769. positions[offset + 9] = positions[3 * 7];
  1770. positions[offset + 10] = positions[3 * 7 + 1];
  1771. positions[offset + 11] = positions[3 * 7 + 2];
  1772. // -y plane
  1773. offset += 3 * 4;
  1774. positions[offset] = positions[3 * 5];
  1775. positions[offset + 1] = positions[3 * 5 + 1];
  1776. positions[offset + 2] = positions[3 * 5 + 2];
  1777. positions[offset + 3] = positions[3];
  1778. positions[offset + 4] = positions[3 + 1];
  1779. positions[offset + 5] = positions[3 + 2];
  1780. positions[offset + 6] = positions[0];
  1781. positions[offset + 7] = positions[1];
  1782. positions[offset + 8] = positions[2];
  1783. positions[offset + 9] = positions[3 * 4];
  1784. positions[offset + 10] = positions[3 * 4 + 1];
  1785. positions[offset + 11] = positions[3 * 4 + 2];
  1786. // +x plane
  1787. offset += 3 * 4;
  1788. positions[offset] = positions[3];
  1789. positions[offset + 1] = positions[3 + 1];
  1790. positions[offset + 2] = positions[3 + 2];
  1791. positions[offset + 3] = positions[3 * 5];
  1792. positions[offset + 4] = positions[3 * 5 + 1];
  1793. positions[offset + 5] = positions[3 * 5 + 2];
  1794. positions[offset + 6] = positions[3 * 6];
  1795. positions[offset + 7] = positions[3 * 6 + 1];
  1796. positions[offset + 8] = positions[3 * 6 + 2];
  1797. positions[offset + 9] = positions[3 * 2];
  1798. positions[offset + 10] = positions[3 * 2 + 1];
  1799. positions[offset + 11] = positions[3 * 2 + 2];
  1800. // +y plane
  1801. offset += 3 * 4;
  1802. positions[offset] = positions[3 * 2];
  1803. positions[offset + 1] = positions[3 * 2 + 1];
  1804. positions[offset + 2] = positions[3 * 2 + 2];
  1805. positions[offset + 3] = positions[3 * 6];
  1806. positions[offset + 4] = positions[3 * 6 + 1];
  1807. positions[offset + 5] = positions[3 * 6 + 2];
  1808. positions[offset + 6] = positions[3 * 7];
  1809. positions[offset + 7] = positions[3 * 7 + 1];
  1810. positions[offset + 8] = positions[3 * 7 + 2];
  1811. positions[offset + 9] = positions[3 * 3];
  1812. positions[offset + 10] = positions[3 * 3 + 1];
  1813. positions[offset + 11] = positions[3 * 3 + 2];
  1814. if (!drawNearPlane) {
  1815. positions = positions.subarray(3 * 4);
  1816. }
  1817. var attributes = new GeometryAttributes.GeometryAttributes({
  1818. position : new GeometryAttribute.GeometryAttribute({
  1819. componentDatatype : ComponentDatatype.ComponentDatatype.DOUBLE,
  1820. componentsPerAttribute : 3,
  1821. values : positions
  1822. })
  1823. });
  1824. if (defined.defined(vertexFormat.normal) || defined.defined(vertexFormat.tangent) || defined.defined(vertexFormat.bitangent) || defined.defined(vertexFormat.st)) {
  1825. var normals = defined.defined(vertexFormat.normal) ? new Float32Array(3 * 4 * numberOfPlanes) : undefined;
  1826. var tangents = defined.defined(vertexFormat.tangent) ? new Float32Array(3 * 4 * numberOfPlanes) : undefined;
  1827. var bitangents = defined.defined(vertexFormat.bitangent) ? new Float32Array(3 * 4 * numberOfPlanes) : undefined;
  1828. var st = defined.defined(vertexFormat.st) ? new Float32Array(2 * 4 * numberOfPlanes) : undefined;
  1829. var x = scratchXDirection;
  1830. var y = scratchYDirection;
  1831. var z = scratchZDirection;
  1832. var negativeX = Cartesian2.Cartesian3.negate(x, scratchNegativeX);
  1833. var negativeY = Cartesian2.Cartesian3.negate(y, scratchNegativeY);
  1834. var negativeZ = Cartesian2.Cartesian3.negate(z, scratchNegativeZ);
  1835. offset = 0;
  1836. if (drawNearPlane) {
  1837. getAttributes(offset, normals, tangents, bitangents, st, negativeZ, x, y); // near
  1838. offset += 3 * 4;
  1839. }
  1840. getAttributes(offset, normals, tangents, bitangents, st, z, negativeX, y); // far
  1841. offset += 3 * 4;
  1842. getAttributes(offset, normals, tangents, bitangents, st, negativeX, negativeZ, y); // -x
  1843. offset += 3 * 4;
  1844. getAttributes(offset, normals, tangents, bitangents, st, negativeY, negativeZ, negativeX); // -y
  1845. offset += 3 * 4;
  1846. getAttributes(offset, normals, tangents, bitangents, st, x, z, y); // +x
  1847. offset += 3 * 4;
  1848. getAttributes(offset, normals, tangents, bitangents, st, y, z, negativeX); // +y
  1849. if (defined.defined(normals)) {
  1850. attributes.normal = new GeometryAttribute.GeometryAttribute({
  1851. componentDatatype : ComponentDatatype.ComponentDatatype.FLOAT,
  1852. componentsPerAttribute : 3,
  1853. values : normals
  1854. });
  1855. }
  1856. if (defined.defined(tangents)) {
  1857. attributes.tangent = new GeometryAttribute.GeometryAttribute({
  1858. componentDatatype : ComponentDatatype.ComponentDatatype.FLOAT,
  1859. componentsPerAttribute : 3,
  1860. values : tangents
  1861. });
  1862. }
  1863. if (defined.defined(bitangents)) {
  1864. attributes.bitangent = new GeometryAttribute.GeometryAttribute({
  1865. componentDatatype : ComponentDatatype.ComponentDatatype.FLOAT,
  1866. componentsPerAttribute : 3,
  1867. values : bitangents
  1868. });
  1869. }
  1870. if (defined.defined(st)) {
  1871. attributes.st = new GeometryAttribute.GeometryAttribute({
  1872. componentDatatype : ComponentDatatype.ComponentDatatype.FLOAT,
  1873. componentsPerAttribute : 2,
  1874. values : st
  1875. });
  1876. }
  1877. }
  1878. var indices = new Uint16Array(6 * numberOfPlanes);
  1879. for (var i = 0; i < numberOfPlanes; ++i) {
  1880. var indexOffset = i * 6;
  1881. var index = i * 4;
  1882. indices[indexOffset] = index;
  1883. indices[indexOffset + 1] = index + 1;
  1884. indices[indexOffset + 2] = index + 2;
  1885. indices[indexOffset + 3] = index;
  1886. indices[indexOffset + 4] = index + 2;
  1887. indices[indexOffset + 5] = index + 3;
  1888. }
  1889. return new GeometryAttribute.Geometry({
  1890. attributes : attributes,
  1891. indices : indices,
  1892. primitiveType : GeometryAttribute.PrimitiveType.TRIANGLES,
  1893. boundingSphere : Transforms.BoundingSphere.fromVertices(positions)
  1894. });
  1895. };
  1896. exports.FrustumGeometry = FrustumGeometry;
  1897. exports.OrthographicFrustum = OrthographicFrustum;
  1898. exports.PerspectiveFrustum = PerspectiveFrustum;
  1899. });