FrustumGeometry-45215f13.js 83 KB

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