影像解译
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

FrustumGeometry-d3ff16d0.js 84KB

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