GeometryPipeline-e8a01ba6.js 114 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685
  1. /* This file is automatically rebuilt by the Cesium build process. */
  2. define(['exports', './when-e6985d2a', './Check-24cae389', './Math-392d0035', './Cartesian2-a5d6dde9', './Transforms-81680c41', './ComponentDatatype-cb08e294', './GeometryAttribute-6d403cd9', './AttributeCompression-114c6354', './EncodedCartesian3-c758025f', './IndexDatatype-1be7d1f8', './IntersectionTests-f17c84f0', './Plane-ac6a1d3e'], function (exports, when, Check, _Math, Cartesian2, Transforms, ComponentDatatype, GeometryAttribute, AttributeCompression, EncodedCartesian3, IndexDatatype, IntersectionTests, Plane) { 'use strict';
  3. var scratchCartesian1 = new Cartesian2.Cartesian3();
  4. var scratchCartesian2 = new Cartesian2.Cartesian3();
  5. var scratchCartesian3 = new Cartesian2.Cartesian3();
  6. /**
  7. * Computes the barycentric coordinates for a point with respect to a triangle.
  8. *
  9. * @function
  10. *
  11. * @param {Cartesian2|Cartesian3} point The point to test.
  12. * @param {Cartesian2|Cartesian3} p0 The first point of the triangle, corresponding to the barycentric x-axis.
  13. * @param {Cartesian2|Cartesian3} p1 The second point of the triangle, corresponding to the barycentric y-axis.
  14. * @param {Cartesian2|Cartesian3} p2 The third point of the triangle, corresponding to the barycentric z-axis.
  15. * @param {Cartesian3} [result] The object onto which to store the result.
  16. * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.
  17. *
  18. * @example
  19. * // Returns Cartesian3.UNIT_X
  20. * var p = new Cesium.Cartesian3(-1.0, 0.0, 0.0);
  21. * var b = Cesium.barycentricCoordinates(p,
  22. * new Cesium.Cartesian3(-1.0, 0.0, 0.0),
  23. * new Cesium.Cartesian3( 1.0, 0.0, 0.0),
  24. * new Cesium.Cartesian3( 0.0, 1.0, 1.0));
  25. */
  26. function barycentricCoordinates(point, p0, p1, p2, result) {
  27. //>>includeStart('debug', pragmas.debug);
  28. Check.Check.defined("point", point);
  29. Check.Check.defined("p0", p0);
  30. Check.Check.defined("p1", p1);
  31. Check.Check.defined("p2", p2);
  32. //>>includeEnd('debug');
  33. if (!when.defined(result)) {
  34. result = new Cartesian2.Cartesian3();
  35. }
  36. // Implementation based on http://www.blackpawn.com/texts/pointinpoly/default.html.
  37. var v0;
  38. var v1;
  39. var v2;
  40. var dot00;
  41. var dot01;
  42. var dot02;
  43. var dot11;
  44. var dot12;
  45. if (!when.defined(p0.z)) {
  46. if (Cartesian2.Cartesian2.equalsEpsilon(point, p0, _Math.CesiumMath.EPSILON14)) {
  47. return Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.UNIT_X, result);
  48. }
  49. if (Cartesian2.Cartesian2.equalsEpsilon(point, p1, _Math.CesiumMath.EPSILON14)) {
  50. return Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.UNIT_Y, result);
  51. }
  52. if (Cartesian2.Cartesian2.equalsEpsilon(point, p2, _Math.CesiumMath.EPSILON14)) {
  53. return Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.UNIT_Z, result);
  54. }
  55. v0 = Cartesian2.Cartesian2.subtract(p1, p0, scratchCartesian1);
  56. v1 = Cartesian2.Cartesian2.subtract(p2, p0, scratchCartesian2);
  57. v2 = Cartesian2.Cartesian2.subtract(point, p0, scratchCartesian3);
  58. dot00 = Cartesian2.Cartesian2.dot(v0, v0);
  59. dot01 = Cartesian2.Cartesian2.dot(v0, v1);
  60. dot02 = Cartesian2.Cartesian2.dot(v0, v2);
  61. dot11 = Cartesian2.Cartesian2.dot(v1, v1);
  62. dot12 = Cartesian2.Cartesian2.dot(v1, v2);
  63. } else {
  64. if (Cartesian2.Cartesian3.equalsEpsilon(point, p0, _Math.CesiumMath.EPSILON14)) {
  65. return Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.UNIT_X, result);
  66. }
  67. if (Cartesian2.Cartesian3.equalsEpsilon(point, p1, _Math.CesiumMath.EPSILON14)) {
  68. return Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.UNIT_Y, result);
  69. }
  70. if (Cartesian2.Cartesian3.equalsEpsilon(point, p2, _Math.CesiumMath.EPSILON14)) {
  71. return Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.UNIT_Z, result);
  72. }
  73. v0 = Cartesian2.Cartesian3.subtract(p1, p0, scratchCartesian1);
  74. v1 = Cartesian2.Cartesian3.subtract(p2, p0, scratchCartesian2);
  75. v2 = Cartesian2.Cartesian3.subtract(point, p0, scratchCartesian3);
  76. dot00 = Cartesian2.Cartesian3.dot(v0, v0);
  77. dot01 = Cartesian2.Cartesian3.dot(v0, v1);
  78. dot02 = Cartesian2.Cartesian3.dot(v0, v2);
  79. dot11 = Cartesian2.Cartesian3.dot(v1, v1);
  80. dot12 = Cartesian2.Cartesian3.dot(v1, v2);
  81. }
  82. result.y = dot11 * dot02 - dot01 * dot12;
  83. result.z = dot00 * dot12 - dot01 * dot02;
  84. var q = dot00 * dot11 - dot01 * dot01;
  85. // This is done to avoid dividing by infinity causing a NaN
  86. if (result.y !== 0) {
  87. result.y /= q;
  88. }
  89. if (result.z !== 0) {
  90. result.z /= q;
  91. }
  92. result.x = 1.0 - result.y - result.z;
  93. return result;
  94. }
  95. /**
  96. * Encapsulates an algorithm to optimize triangles for the post
  97. * vertex-shader cache. This is based on the 2007 SIGGRAPH paper
  98. * 'Fast Triangle Reordering for Vertex Locality and Reduced Overdraw.'
  99. * The runtime is linear but several passes are made.
  100. *
  101. * @namespace Tipsify
  102. *
  103. * @see <a href='http://gfx.cs.princeton.edu/pubs/Sander_2007_%3ETR/tipsy.pdf'>
  104. * Fast Triangle Reordering for Vertex Locality and Reduced Overdraw</a>
  105. * by Sander, Nehab, and Barczak
  106. *
  107. * @private
  108. */
  109. var Tipsify = {};
  110. /**
  111. * Calculates the average cache miss ratio (ACMR) for a given set of indices.
  112. *
  113. * @param {Object} options Object with the following properties:
  114. * @param {Number[]} options.indices Lists triads of numbers corresponding to the indices of the vertices
  115. * in the vertex buffer that define the geometry's triangles.
  116. * @param {Number} [options.maximumIndex] The maximum value of the elements in <code>args.indices</code>.
  117. * If not supplied, this value will be computed.
  118. * @param {Number} [options.cacheSize=24] The number of vertices that can be stored in the cache at any one time.
  119. * @returns {Number} The average cache miss ratio (ACMR).
  120. *
  121. * @exception {DeveloperError} indices length must be a multiple of three.
  122. * @exception {DeveloperError} cacheSize must be greater than two.
  123. *
  124. * @example
  125. * var indices = [0, 1, 2, 3, 4, 5];
  126. * var maxIndex = 5;
  127. * var cacheSize = 3;
  128. * var acmr = Cesium.Tipsify.calculateACMR({indices : indices, maxIndex : maxIndex, cacheSize : cacheSize});
  129. */
  130. Tipsify.calculateACMR = function (options) {
  131. options = when.defaultValue(options, when.defaultValue.EMPTY_OBJECT);
  132. var indices = options.indices;
  133. var maximumIndex = options.maximumIndex;
  134. var cacheSize = when.defaultValue(options.cacheSize, 24);
  135. //>>includeStart('debug', pragmas.debug);
  136. if (!when.defined(indices)) {
  137. throw new Check.DeveloperError("indices is required.");
  138. }
  139. //>>includeEnd('debug');
  140. var numIndices = indices.length;
  141. //>>includeStart('debug', pragmas.debug);
  142. if (numIndices < 3 || numIndices % 3 !== 0) {
  143. throw new Check.DeveloperError("indices length must be a multiple of three.");
  144. }
  145. if (maximumIndex <= 0) {
  146. throw new Check.DeveloperError("maximumIndex must be greater than zero.");
  147. }
  148. if (cacheSize < 3) {
  149. throw new Check.DeveloperError("cacheSize must be greater than two.");
  150. }
  151. //>>includeEnd('debug');
  152. // Compute the maximumIndex if not given
  153. if (!when.defined(maximumIndex)) {
  154. maximumIndex = 0;
  155. var currentIndex = 0;
  156. var intoIndices = indices[currentIndex];
  157. while (currentIndex < numIndices) {
  158. if (intoIndices > maximumIndex) {
  159. maximumIndex = intoIndices;
  160. }
  161. ++currentIndex;
  162. intoIndices = indices[currentIndex];
  163. }
  164. }
  165. // Vertex time stamps
  166. var vertexTimeStamps = [];
  167. for (var i = 0; i < maximumIndex + 1; i++) {
  168. vertexTimeStamps[i] = 0;
  169. }
  170. // Cache processing
  171. var s = cacheSize + 1;
  172. for (var j = 0; j < numIndices; ++j) {
  173. if (s - vertexTimeStamps[indices[j]] > cacheSize) {
  174. vertexTimeStamps[indices[j]] = s;
  175. ++s;
  176. }
  177. }
  178. return (s - cacheSize + 1) / (numIndices / 3);
  179. };
  180. /**
  181. * Optimizes triangles for the post-vertex shader cache.
  182. *
  183. * @param {Object} options Object with the following properties:
  184. * @param {Number[]} options.indices Lists triads of numbers corresponding to the indices of the vertices
  185. * in the vertex buffer that define the geometry's triangles.
  186. * @param {Number} [options.maximumIndex] The maximum value of the elements in <code>args.indices</code>.
  187. * If not supplied, this value will be computed.
  188. * @param {Number} [options.cacheSize=24] The number of vertices that can be stored in the cache at any one time.
  189. * @returns {Number[]} A list of the input indices in an optimized order.
  190. *
  191. * @exception {DeveloperError} indices length must be a multiple of three.
  192. * @exception {DeveloperError} cacheSize must be greater than two.
  193. *
  194. * @example
  195. * var indices = [0, 1, 2, 3, 4, 5];
  196. * var maxIndex = 5;
  197. * var cacheSize = 3;
  198. * var reorderedIndices = Cesium.Tipsify.tipsify({indices : indices, maxIndex : maxIndex, cacheSize : cacheSize});
  199. */
  200. Tipsify.tipsify = function (options) {
  201. options = when.defaultValue(options, when.defaultValue.EMPTY_OBJECT);
  202. var indices = options.indices;
  203. var maximumIndex = options.maximumIndex;
  204. var cacheSize = when.defaultValue(options.cacheSize, 24);
  205. var cursor;
  206. function skipDeadEnd(vertices, deadEnd, indices, maximumIndexPlusOne) {
  207. while (deadEnd.length >= 1) {
  208. // while the stack is not empty
  209. var d = deadEnd[deadEnd.length - 1]; // top of the stack
  210. deadEnd.splice(deadEnd.length - 1, 1); // pop the stack
  211. if (vertices[d].numLiveTriangles > 0) {
  212. return d;
  213. }
  214. }
  215. while (cursor < maximumIndexPlusOne) {
  216. if (vertices[cursor].numLiveTriangles > 0) {
  217. ++cursor;
  218. return cursor - 1;
  219. }
  220. ++cursor;
  221. }
  222. return -1;
  223. }
  224. function getNextVertex(
  225. indices,
  226. cacheSize,
  227. oneRing,
  228. vertices,
  229. s,
  230. deadEnd,
  231. maximumIndexPlusOne
  232. ) {
  233. var n = -1;
  234. var p;
  235. var m = -1;
  236. var itOneRing = 0;
  237. while (itOneRing < oneRing.length) {
  238. var index = oneRing[itOneRing];
  239. if (vertices[index].numLiveTriangles) {
  240. p = 0;
  241. if (
  242. s -
  243. vertices[index].timeStamp +
  244. 2 * vertices[index].numLiveTriangles <=
  245. cacheSize
  246. ) {
  247. p = s - vertices[index].timeStamp;
  248. }
  249. if (p > m || m === -1) {
  250. m = p;
  251. n = index;
  252. }
  253. }
  254. ++itOneRing;
  255. }
  256. if (n === -1) {
  257. return skipDeadEnd(vertices, deadEnd, indices, maximumIndexPlusOne);
  258. }
  259. return n;
  260. }
  261. //>>includeStart('debug', pragmas.debug);
  262. if (!when.defined(indices)) {
  263. throw new Check.DeveloperError("indices is required.");
  264. }
  265. //>>includeEnd('debug');
  266. var numIndices = indices.length;
  267. //>>includeStart('debug', pragmas.debug);
  268. if (numIndices < 3 || numIndices % 3 !== 0) {
  269. throw new Check.DeveloperError("indices length must be a multiple of three.");
  270. }
  271. if (maximumIndex <= 0) {
  272. throw new Check.DeveloperError("maximumIndex must be greater than zero.");
  273. }
  274. if (cacheSize < 3) {
  275. throw new Check.DeveloperError("cacheSize must be greater than two.");
  276. }
  277. //>>includeEnd('debug');
  278. // Determine maximum index
  279. var maximumIndexPlusOne = 0;
  280. var currentIndex = 0;
  281. var intoIndices = indices[currentIndex];
  282. var endIndex = numIndices;
  283. if (when.defined(maximumIndex)) {
  284. maximumIndexPlusOne = maximumIndex + 1;
  285. } else {
  286. while (currentIndex < endIndex) {
  287. if (intoIndices > maximumIndexPlusOne) {
  288. maximumIndexPlusOne = intoIndices;
  289. }
  290. ++currentIndex;
  291. intoIndices = indices[currentIndex];
  292. }
  293. if (maximumIndexPlusOne === -1) {
  294. return 0;
  295. }
  296. ++maximumIndexPlusOne;
  297. }
  298. // Vertices
  299. var vertices = [];
  300. var i;
  301. for (i = 0; i < maximumIndexPlusOne; i++) {
  302. vertices[i] = {
  303. numLiveTriangles: 0,
  304. timeStamp: 0,
  305. vertexTriangles: [],
  306. };
  307. }
  308. currentIndex = 0;
  309. var triangle = 0;
  310. while (currentIndex < endIndex) {
  311. vertices[indices[currentIndex]].vertexTriangles.push(triangle);
  312. ++vertices[indices[currentIndex]].numLiveTriangles;
  313. vertices[indices[currentIndex + 1]].vertexTriangles.push(triangle);
  314. ++vertices[indices[currentIndex + 1]].numLiveTriangles;
  315. vertices[indices[currentIndex + 2]].vertexTriangles.push(triangle);
  316. ++vertices[indices[currentIndex + 2]].numLiveTriangles;
  317. ++triangle;
  318. currentIndex += 3;
  319. }
  320. // Starting index
  321. var f = 0;
  322. // Time Stamp
  323. var s = cacheSize + 1;
  324. cursor = 1;
  325. // Process
  326. var oneRing = [];
  327. var deadEnd = []; //Stack
  328. var vertex;
  329. var intoVertices;
  330. var currentOutputIndex = 0;
  331. var outputIndices = [];
  332. var numTriangles = numIndices / 3;
  333. var triangleEmitted = [];
  334. for (i = 0; i < numTriangles; i++) {
  335. triangleEmitted[i] = false;
  336. }
  337. var index;
  338. var limit;
  339. while (f !== -1) {
  340. oneRing = [];
  341. intoVertices = vertices[f];
  342. limit = intoVertices.vertexTriangles.length;
  343. for (var k = 0; k < limit; ++k) {
  344. triangle = intoVertices.vertexTriangles[k];
  345. if (!triangleEmitted[triangle]) {
  346. triangleEmitted[triangle] = true;
  347. currentIndex = triangle + triangle + triangle;
  348. for (var j = 0; j < 3; ++j) {
  349. // Set this index as a possible next index
  350. index = indices[currentIndex];
  351. oneRing.push(index);
  352. deadEnd.push(index);
  353. // Output index
  354. outputIndices[currentOutputIndex] = index;
  355. ++currentOutputIndex;
  356. // Cache processing
  357. vertex = vertices[index];
  358. --vertex.numLiveTriangles;
  359. if (s - vertex.timeStamp > cacheSize) {
  360. vertex.timeStamp = s;
  361. ++s;
  362. }
  363. ++currentIndex;
  364. }
  365. }
  366. }
  367. f = getNextVertex(
  368. indices,
  369. cacheSize,
  370. oneRing,
  371. vertices,
  372. s,
  373. deadEnd,
  374. maximumIndexPlusOne
  375. );
  376. }
  377. return outputIndices;
  378. };
  379. /**
  380. * Content pipeline functions for geometries.
  381. *
  382. * @namespace GeometryPipeline
  383. *
  384. * @see Geometry
  385. */
  386. var GeometryPipeline = {};
  387. function addTriangle(lines, index, i0, i1, i2) {
  388. lines[index++] = i0;
  389. lines[index++] = i1;
  390. lines[index++] = i1;
  391. lines[index++] = i2;
  392. lines[index++] = i2;
  393. lines[index] = i0;
  394. }
  395. function trianglesToLines(triangles) {
  396. var count = triangles.length;
  397. var size = (count / 3) * 6;
  398. var lines = IndexDatatype.IndexDatatype.createTypedArray(count, size);
  399. var index = 0;
  400. for (var i = 0; i < count; i += 3, index += 6) {
  401. addTriangle(lines, index, triangles[i], triangles[i + 1], triangles[i + 2]);
  402. }
  403. return lines;
  404. }
  405. function triangleStripToLines(triangles) {
  406. var count = triangles.length;
  407. if (count >= 3) {
  408. var size = (count - 2) * 6;
  409. var lines = IndexDatatype.IndexDatatype.createTypedArray(count, size);
  410. addTriangle(lines, 0, triangles[0], triangles[1], triangles[2]);
  411. var index = 6;
  412. for (var i = 3; i < count; ++i, index += 6) {
  413. addTriangle(
  414. lines,
  415. index,
  416. triangles[i - 1],
  417. triangles[i],
  418. triangles[i - 2]
  419. );
  420. }
  421. return lines;
  422. }
  423. return new Uint16Array();
  424. }
  425. function triangleFanToLines(triangles) {
  426. if (triangles.length > 0) {
  427. var count = triangles.length - 1;
  428. var size = (count - 1) * 6;
  429. var lines = IndexDatatype.IndexDatatype.createTypedArray(count, size);
  430. var base = triangles[0];
  431. var index = 0;
  432. for (var i = 1; i < count; ++i, index += 6) {
  433. addTriangle(lines, index, base, triangles[i], triangles[i + 1]);
  434. }
  435. return lines;
  436. }
  437. return new Uint16Array();
  438. }
  439. /**
  440. * Converts a geometry's triangle indices to line indices. If the geometry has an <code>indices</code>
  441. * and its <code>primitiveType</code> is <code>TRIANGLES</code>, <code>TRIANGLE_STRIP</code>,
  442. * <code>TRIANGLE_FAN</code>, it is converted to <code>LINES</code>; otherwise, the geometry is not changed.
  443. * <p>
  444. * This is commonly used to create a wireframe geometry for visual debugging.
  445. * </p>
  446. *
  447. * @param {Geometry} geometry The geometry to modify.
  448. * @returns {Geometry} The modified <code>geometry</code> argument, with its triangle indices converted to lines.
  449. *
  450. * @exception {DeveloperError} geometry.primitiveType must be TRIANGLES, TRIANGLE_STRIP, or TRIANGLE_FAN.
  451. *
  452. * @example
  453. * geometry = Cesium.GeometryPipeline.toWireframe(geometry);
  454. */
  455. GeometryPipeline.toWireframe = function (geometry) {
  456. //>>includeStart('debug', pragmas.debug);
  457. if (!when.defined(geometry)) {
  458. throw new Check.DeveloperError("geometry is required.");
  459. }
  460. //>>includeEnd('debug');
  461. var indices = geometry.indices;
  462. if (when.defined(indices)) {
  463. switch (geometry.primitiveType) {
  464. case GeometryAttribute.PrimitiveType.TRIANGLES:
  465. geometry.indices = trianglesToLines(indices);
  466. break;
  467. case GeometryAttribute.PrimitiveType.TRIANGLE_STRIP:
  468. geometry.indices = triangleStripToLines(indices);
  469. break;
  470. case GeometryAttribute.PrimitiveType.TRIANGLE_FAN:
  471. geometry.indices = triangleFanToLines(indices);
  472. break;
  473. //>>includeStart('debug', pragmas.debug);
  474. default:
  475. throw new Check.DeveloperError(
  476. "geometry.primitiveType must be TRIANGLES, TRIANGLE_STRIP, or TRIANGLE_FAN."
  477. );
  478. //>>includeEnd('debug');
  479. }
  480. geometry.primitiveType = GeometryAttribute.PrimitiveType.LINES;
  481. }
  482. return geometry;
  483. };
  484. /**
  485. * Creates a new {@link Geometry} with <code>LINES</code> representing the provided
  486. * attribute (<code>attributeName</code>) for the provided geometry. This is used to
  487. * visualize vector attributes like normals, tangents, and bitangents.
  488. *
  489. * @param {Geometry} geometry The <code>Geometry</code> instance with the attribute.
  490. * @param {String} [attributeName='normal'] The name of the attribute.
  491. * @param {Number} [length=10000.0] The length of each line segment in meters. This can be negative to point the vector in the opposite direction.
  492. * @returns {Geometry} A new <code>Geometry</code> instance with line segments for the vector.
  493. *
  494. * @exception {DeveloperError} geometry.attributes must have an attribute with the same name as the attributeName parameter.
  495. *
  496. * @example
  497. * var geometry = Cesium.GeometryPipeline.createLineSegmentsForVectors(instance.geometry, 'bitangent', 100000.0);
  498. */
  499. GeometryPipeline.createLineSegmentsForVectors = function (
  500. geometry,
  501. attributeName,
  502. length
  503. ) {
  504. attributeName = when.defaultValue(attributeName, "normal");
  505. //>>includeStart('debug', pragmas.debug);
  506. if (!when.defined(geometry)) {
  507. throw new Check.DeveloperError("geometry is required.");
  508. }
  509. if (!when.defined(geometry.attributes.position)) {
  510. throw new Check.DeveloperError("geometry.attributes.position is required.");
  511. }
  512. if (!when.defined(geometry.attributes[attributeName])) {
  513. throw new Check.DeveloperError(
  514. "geometry.attributes must have an attribute with the same name as the attributeName parameter, " +
  515. attributeName +
  516. "."
  517. );
  518. }
  519. //>>includeEnd('debug');
  520. length = when.defaultValue(length, 10000.0);
  521. var positions = geometry.attributes.position.values;
  522. var vectors = geometry.attributes[attributeName].values;
  523. var positionsLength = positions.length;
  524. var newPositions = new Float64Array(2 * positionsLength);
  525. var j = 0;
  526. for (var i = 0; i < positionsLength; i += 3) {
  527. newPositions[j++] = positions[i];
  528. newPositions[j++] = positions[i + 1];
  529. newPositions[j++] = positions[i + 2];
  530. newPositions[j++] = positions[i] + vectors[i] * length;
  531. newPositions[j++] = positions[i + 1] + vectors[i + 1] * length;
  532. newPositions[j++] = positions[i + 2] + vectors[i + 2] * length;
  533. }
  534. var newBoundingSphere;
  535. var bs = geometry.boundingSphere;
  536. if (when.defined(bs)) {
  537. newBoundingSphere = new Transforms.BoundingSphere(bs.center, bs.radius + length);
  538. }
  539. return new GeometryAttribute.Geometry({
  540. attributes: {
  541. position: new GeometryAttribute.GeometryAttribute({
  542. componentDatatype: ComponentDatatype.ComponentDatatype.DOUBLE,
  543. componentsPerAttribute: 3,
  544. values: newPositions,
  545. }),
  546. },
  547. primitiveType: GeometryAttribute.PrimitiveType.LINES,
  548. boundingSphere: newBoundingSphere,
  549. });
  550. };
  551. /**
  552. * Creates an object that maps attribute names to unique locations (indices)
  553. * for matching vertex attributes and shader programs.
  554. *
  555. * @param {Geometry} geometry The geometry, which is not modified, to create the object for.
  556. * @returns {Object} An object with attribute name / index pairs.
  557. *
  558. * @example
  559. * var attributeLocations = Cesium.GeometryPipeline.createAttributeLocations(geometry);
  560. * // Example output
  561. * // {
  562. * // 'position' : 0,
  563. * // 'normal' : 1
  564. * // }
  565. */
  566. GeometryPipeline.createAttributeLocations = function (geometry) {
  567. //>>includeStart('debug', pragmas.debug);
  568. if (!when.defined(geometry)) {
  569. throw new Check.DeveloperError("geometry is required.");
  570. }
  571. //>>includeEnd('debug')
  572. // There can be a WebGL performance hit when attribute 0 is disabled, so
  573. // assign attribute locations to well-known attributes.
  574. var semantics = [
  575. "position",
  576. "positionHigh",
  577. "positionLow",
  578. // From VertexFormat.position - after 2D projection and high-precision encoding
  579. "position3DHigh",
  580. "position3DLow",
  581. "position2DHigh",
  582. "position2DLow",
  583. // From Primitive
  584. "pickColor",
  585. // From VertexFormat
  586. "normal",
  587. "st",
  588. "tangent",
  589. "bitangent",
  590. // For shadow volumes
  591. "extrudeDirection",
  592. // From compressing texture coordinates and normals
  593. "compressedAttributes",
  594. ];
  595. var attributes = geometry.attributes;
  596. var indices = {};
  597. var j = 0;
  598. var i;
  599. var len = semantics.length;
  600. // Attribute locations for well-known attributes
  601. for (i = 0; i < len; ++i) {
  602. var semantic = semantics[i];
  603. if (when.defined(attributes[semantic])) {
  604. indices[semantic] = j++;
  605. }
  606. }
  607. // Locations for custom attributes
  608. for (var name in attributes) {
  609. if (attributes.hasOwnProperty(name) && !when.defined(indices[name])) {
  610. indices[name] = j++;
  611. }
  612. }
  613. return indices;
  614. };
  615. /**
  616. * Reorders a geometry's attributes and <code>indices</code> to achieve better performance from the GPU's pre-vertex-shader cache.
  617. *
  618. * @param {Geometry} geometry The geometry to modify.
  619. * @returns {Geometry} The modified <code>geometry</code> argument, with its attributes and indices reordered for the GPU's pre-vertex-shader cache.
  620. *
  621. * @exception {DeveloperError} Each attribute array in geometry.attributes must have the same number of attributes.
  622. *
  623. *
  624. * @example
  625. * geometry = Cesium.GeometryPipeline.reorderForPreVertexCache(geometry);
  626. *
  627. * @see GeometryPipeline.reorderForPostVertexCache
  628. */
  629. GeometryPipeline.reorderForPreVertexCache = function (geometry) {
  630. //>>includeStart('debug', pragmas.debug);
  631. if (!when.defined(geometry)) {
  632. throw new Check.DeveloperError("geometry is required.");
  633. }
  634. //>>includeEnd('debug');
  635. var numVertices = GeometryAttribute.Geometry.computeNumberOfVertices(geometry);
  636. var indices = geometry.indices;
  637. if (when.defined(indices)) {
  638. var indexCrossReferenceOldToNew = new Int32Array(numVertices);
  639. for (var i = 0; i < numVertices; i++) {
  640. indexCrossReferenceOldToNew[i] = -1;
  641. }
  642. // Construct cross reference and reorder indices
  643. var indicesIn = indices;
  644. var numIndices = indicesIn.length;
  645. var indicesOut = IndexDatatype.IndexDatatype.createTypedArray(numVertices, numIndices);
  646. var intoIndicesIn = 0;
  647. var intoIndicesOut = 0;
  648. var nextIndex = 0;
  649. var tempIndex;
  650. while (intoIndicesIn < numIndices) {
  651. tempIndex = indexCrossReferenceOldToNew[indicesIn[intoIndicesIn]];
  652. if (tempIndex !== -1) {
  653. indicesOut[intoIndicesOut] = tempIndex;
  654. } else {
  655. tempIndex = indicesIn[intoIndicesIn];
  656. indexCrossReferenceOldToNew[tempIndex] = nextIndex;
  657. indicesOut[intoIndicesOut] = nextIndex;
  658. ++nextIndex;
  659. }
  660. ++intoIndicesIn;
  661. ++intoIndicesOut;
  662. }
  663. geometry.indices = indicesOut;
  664. // Reorder attributes
  665. var attributes = geometry.attributes;
  666. for (var property in attributes) {
  667. if (
  668. attributes.hasOwnProperty(property) &&
  669. when.defined(attributes[property]) &&
  670. when.defined(attributes[property].values)
  671. ) {
  672. var attribute = attributes[property];
  673. var elementsIn = attribute.values;
  674. var intoElementsIn = 0;
  675. var numComponents = attribute.componentsPerAttribute;
  676. var elementsOut = ComponentDatatype.ComponentDatatype.createTypedArray(
  677. attribute.componentDatatype,
  678. nextIndex * numComponents
  679. );
  680. while (intoElementsIn < numVertices) {
  681. var temp = indexCrossReferenceOldToNew[intoElementsIn];
  682. if (temp !== -1) {
  683. for (var j = 0; j < numComponents; j++) {
  684. elementsOut[numComponents * temp + j] =
  685. elementsIn[numComponents * intoElementsIn + j];
  686. }
  687. }
  688. ++intoElementsIn;
  689. }
  690. attribute.values = elementsOut;
  691. }
  692. }
  693. }
  694. return geometry;
  695. };
  696. /**
  697. * Reorders a geometry's <code>indices</code> to achieve better performance from the GPU's
  698. * post vertex-shader cache by using the Tipsify algorithm. If the geometry <code>primitiveType</code>
  699. * is not <code>TRIANGLES</code> or the geometry does not have an <code>indices</code>, this function has no effect.
  700. *
  701. * @param {Geometry} geometry The geometry to modify.
  702. * @param {Number} [cacheCapacity=24] The number of vertices that can be held in the GPU's vertex cache.
  703. * @returns {Geometry} The modified <code>geometry</code> argument, with its indices reordered for the post-vertex-shader cache.
  704. *
  705. * @exception {DeveloperError} cacheCapacity must be greater than two.
  706. *
  707. *
  708. * @example
  709. * geometry = Cesium.GeometryPipeline.reorderForPostVertexCache(geometry);
  710. *
  711. * @see GeometryPipeline.reorderForPreVertexCache
  712. * @see {@link http://gfx.cs.princ0eton.edu/pubs/Sander_2007_%3ETR/tipsy.pdf|Fast Triangle Reordering for Vertex Locality and Reduced Overdraw}
  713. * by Sander, Nehab, and Barczak
  714. */
  715. GeometryPipeline.reorderForPostVertexCache = function (
  716. geometry,
  717. cacheCapacity
  718. ) {
  719. //>>includeStart('debug', pragmas.debug);
  720. if (!when.defined(geometry)) {
  721. throw new Check.DeveloperError("geometry is required.");
  722. }
  723. //>>includeEnd('debug');
  724. var indices = geometry.indices;
  725. if (geometry.primitiveType === GeometryAttribute.PrimitiveType.TRIANGLES && when.defined(indices)) {
  726. var numIndices = indices.length;
  727. var maximumIndex = 0;
  728. for (var j = 0; j < numIndices; j++) {
  729. if (indices[j] > maximumIndex) {
  730. maximumIndex = indices[j];
  731. }
  732. }
  733. geometry.indices = Tipsify.tipsify({
  734. indices: indices,
  735. maximumIndex: maximumIndex,
  736. cacheSize: cacheCapacity,
  737. });
  738. }
  739. return geometry;
  740. };
  741. function copyAttributesDescriptions(attributes) {
  742. var newAttributes = {};
  743. for (var attribute in attributes) {
  744. if (
  745. attributes.hasOwnProperty(attribute) &&
  746. when.defined(attributes[attribute]) &&
  747. when.defined(attributes[attribute].values)
  748. ) {
  749. var attr = attributes[attribute];
  750. newAttributes[attribute] = new GeometryAttribute.GeometryAttribute({
  751. componentDatatype: attr.componentDatatype,
  752. componentsPerAttribute: attr.componentsPerAttribute,
  753. normalize: attr.normalize,
  754. values: [],
  755. });
  756. }
  757. }
  758. return newAttributes;
  759. }
  760. function copyVertex(destinationAttributes, sourceAttributes, index) {
  761. for (var attribute in sourceAttributes) {
  762. if (
  763. sourceAttributes.hasOwnProperty(attribute) &&
  764. when.defined(sourceAttributes[attribute]) &&
  765. when.defined(sourceAttributes[attribute].values)
  766. ) {
  767. var attr = sourceAttributes[attribute];
  768. for (var k = 0; k < attr.componentsPerAttribute; ++k) {
  769. destinationAttributes[attribute].values.push(
  770. attr.values[index * attr.componentsPerAttribute + k]
  771. );
  772. }
  773. }
  774. }
  775. }
  776. /**
  777. * Splits a geometry into multiple geometries, if necessary, to ensure that indices in the
  778. * <code>indices</code> fit into unsigned shorts. This is used to meet the WebGL requirements
  779. * when unsigned int indices are not supported.
  780. * <p>
  781. * If the geometry does not have any <code>indices</code>, this function has no effect.
  782. * </p>
  783. *
  784. * @param {Geometry} geometry The geometry to be split into multiple geometries.
  785. * @returns {Geometry[]} An array of geometries, each with indices that fit into unsigned shorts.
  786. *
  787. * @exception {DeveloperError} geometry.primitiveType must equal to PrimitiveType.TRIANGLES, PrimitiveType.LINES, or PrimitiveType.POINTS
  788. * @exception {DeveloperError} All geometry attribute lists must have the same number of attributes.
  789. *
  790. * @example
  791. * var geometries = Cesium.GeometryPipeline.fitToUnsignedShortIndices(geometry);
  792. */
  793. GeometryPipeline.fitToUnsignedShortIndices = function (geometry) {
  794. //>>includeStart('debug', pragmas.debug);
  795. if (!when.defined(geometry)) {
  796. throw new Check.DeveloperError("geometry is required.");
  797. }
  798. if (
  799. when.defined(geometry.indices) &&
  800. geometry.primitiveType !== GeometryAttribute.PrimitiveType.TRIANGLES &&
  801. geometry.primitiveType !== GeometryAttribute.PrimitiveType.LINES &&
  802. geometry.primitiveType !== GeometryAttribute.PrimitiveType.POINTS
  803. ) {
  804. throw new Check.DeveloperError(
  805. "geometry.primitiveType must equal to PrimitiveType.TRIANGLES, PrimitiveType.LINES, or PrimitiveType.POINTS."
  806. );
  807. }
  808. //>>includeEnd('debug');
  809. var geometries = [];
  810. // If there's an index list and more than 64K attributes, it is possible that
  811. // some indices are outside the range of unsigned short [0, 64K - 1]
  812. var numberOfVertices = GeometryAttribute.Geometry.computeNumberOfVertices(geometry);
  813. if (
  814. when.defined(geometry.indices) &&
  815. numberOfVertices >= _Math.CesiumMath.SIXTY_FOUR_KILOBYTES
  816. ) {
  817. var oldToNewIndex = [];
  818. var newIndices = [];
  819. var currentIndex = 0;
  820. var newAttributes = copyAttributesDescriptions(geometry.attributes);
  821. var originalIndices = geometry.indices;
  822. var numberOfIndices = originalIndices.length;
  823. var indicesPerPrimitive;
  824. if (geometry.primitiveType === GeometryAttribute.PrimitiveType.TRIANGLES) {
  825. indicesPerPrimitive = 3;
  826. } else if (geometry.primitiveType === GeometryAttribute.PrimitiveType.LINES) {
  827. indicesPerPrimitive = 2;
  828. } else if (geometry.primitiveType === GeometryAttribute.PrimitiveType.POINTS) {
  829. indicesPerPrimitive = 1;
  830. }
  831. for (var j = 0; j < numberOfIndices; j += indicesPerPrimitive) {
  832. for (var k = 0; k < indicesPerPrimitive; ++k) {
  833. var x = originalIndices[j + k];
  834. var i = oldToNewIndex[x];
  835. if (!when.defined(i)) {
  836. i = currentIndex++;
  837. oldToNewIndex[x] = i;
  838. copyVertex(newAttributes, geometry.attributes, x);
  839. }
  840. newIndices.push(i);
  841. }
  842. if (
  843. currentIndex + indicesPerPrimitive >=
  844. _Math.CesiumMath.SIXTY_FOUR_KILOBYTES
  845. ) {
  846. geometries.push(
  847. new GeometryAttribute.Geometry({
  848. attributes: newAttributes,
  849. indices: newIndices,
  850. primitiveType: geometry.primitiveType,
  851. boundingSphere: geometry.boundingSphere,
  852. boundingSphereCV: geometry.boundingSphereCV,
  853. })
  854. );
  855. // Reset for next vertex-array
  856. oldToNewIndex = [];
  857. newIndices = [];
  858. currentIndex = 0;
  859. newAttributes = copyAttributesDescriptions(geometry.attributes);
  860. }
  861. }
  862. if (newIndices.length !== 0) {
  863. geometries.push(
  864. new GeometryAttribute.Geometry({
  865. attributes: newAttributes,
  866. indices: newIndices,
  867. primitiveType: geometry.primitiveType,
  868. boundingSphere: geometry.boundingSphere,
  869. boundingSphereCV: geometry.boundingSphereCV,
  870. })
  871. );
  872. }
  873. } else {
  874. // No need to split into multiple geometries
  875. geometries.push(geometry);
  876. }
  877. return geometries;
  878. };
  879. var scratchProjectTo2DCartesian3 = new Cartesian2.Cartesian3();
  880. var scratchProjectTo2DCartographic = new Cartesian2.Cartographic();
  881. /**
  882. * Projects a geometry's 3D <code>position</code> attribute to 2D, replacing the <code>position</code>
  883. * attribute with separate <code>position3D</code> and <code>position2D</code> attributes.
  884. * <p>
  885. * If the geometry does not have a <code>position</code>, this function has no effect.
  886. * </p>
  887. *
  888. * @param {Geometry} geometry The geometry to modify.
  889. * @param {String} attributeName The name of the attribute.
  890. * @param {String} attributeName3D The name of the attribute in 3D.
  891. * @param {String} attributeName2D The name of the attribute in 2D.
  892. * @param {Object} [projection=new GeographicProjection()] The projection to use.
  893. * @returns {Geometry} The modified <code>geometry</code> argument with <code>position3D</code> and <code>position2D</code> attributes.
  894. *
  895. * @exception {DeveloperError} geometry must have attribute matching the attributeName argument.
  896. * @exception {DeveloperError} The attribute componentDatatype must be ComponentDatatype.DOUBLE.
  897. * @exception {DeveloperError} Could not project a point to 2D.
  898. *
  899. * @example
  900. * geometry = Cesium.GeometryPipeline.projectTo2D(geometry, 'position', 'position3D', 'position2D');
  901. */
  902. GeometryPipeline.projectTo2D = function (
  903. geometry,
  904. attributeName,
  905. attributeName3D,
  906. attributeName2D,
  907. projection
  908. ) {
  909. //>>includeStart('debug', pragmas.debug);
  910. if (!when.defined(geometry)) {
  911. throw new Check.DeveloperError("geometry is required.");
  912. }
  913. if (!when.defined(attributeName)) {
  914. throw new Check.DeveloperError("attributeName is required.");
  915. }
  916. if (!when.defined(attributeName3D)) {
  917. throw new Check.DeveloperError("attributeName3D is required.");
  918. }
  919. if (!when.defined(attributeName2D)) {
  920. throw new Check.DeveloperError("attributeName2D is required.");
  921. }
  922. if (!when.defined(geometry.attributes[attributeName])) {
  923. throw new Check.DeveloperError(
  924. "geometry must have attribute matching the attributeName argument: " +
  925. attributeName +
  926. "."
  927. );
  928. }
  929. if (
  930. geometry.attributes[attributeName].componentDatatype !==
  931. ComponentDatatype.ComponentDatatype.DOUBLE
  932. ) {
  933. throw new Check.DeveloperError(
  934. "The attribute componentDatatype must be ComponentDatatype.DOUBLE."
  935. );
  936. }
  937. //>>includeEnd('debug');
  938. var attribute = geometry.attributes[attributeName];
  939. projection = when.defined(projection) ? projection : new Transforms.GeographicProjection();
  940. var ellipsoid = projection.ellipsoid;
  941. // Project original values to 2D.
  942. var values3D = attribute.values;
  943. var projectedValues = new Float64Array(values3D.length);
  944. var index = 0;
  945. for (var i = 0; i < values3D.length; i += 3) {
  946. var value = Cartesian2.Cartesian3.fromArray(values3D, i, scratchProjectTo2DCartesian3);
  947. var lonLat = ellipsoid.cartesianToCartographic(
  948. value,
  949. scratchProjectTo2DCartographic
  950. );
  951. //>>includeStart('debug', pragmas.debug);
  952. if (!when.defined(lonLat)) {
  953. throw new Check.DeveloperError(
  954. "Could not project point (" +
  955. value.x +
  956. ", " +
  957. value.y +
  958. ", " +
  959. value.z +
  960. ") to 2D."
  961. );
  962. }
  963. //>>includeEnd('debug');
  964. var projectedLonLat = projection.project(
  965. lonLat,
  966. scratchProjectTo2DCartesian3
  967. );
  968. projectedValues[index++] = projectedLonLat.x;
  969. projectedValues[index++] = projectedLonLat.y;
  970. projectedValues[index++] = projectedLonLat.z;
  971. }
  972. // Rename original cartesians to WGS84 cartesians.
  973. geometry.attributes[attributeName3D] = attribute;
  974. // Replace original cartesians with 2D projected cartesians
  975. geometry.attributes[attributeName2D] = new GeometryAttribute.GeometryAttribute({
  976. componentDatatype: ComponentDatatype.ComponentDatatype.DOUBLE,
  977. componentsPerAttribute: 3,
  978. values: projectedValues,
  979. });
  980. delete geometry.attributes[attributeName];
  981. return geometry;
  982. };
  983. var encodedResult = {
  984. high: 0.0,
  985. low: 0.0,
  986. };
  987. /**
  988. * Encodes floating-point geometry attribute values as two separate attributes to improve
  989. * rendering precision.
  990. * <p>
  991. * This is commonly used to create high-precision position vertex attributes.
  992. * </p>
  993. *
  994. * @param {Geometry} geometry The geometry to modify.
  995. * @param {String} attributeName The name of the attribute.
  996. * @param {String} attributeHighName The name of the attribute for the encoded high bits.
  997. * @param {String} attributeLowName The name of the attribute for the encoded low bits.
  998. * @returns {Geometry} The modified <code>geometry</code> argument, with its encoded attribute.
  999. *
  1000. * @exception {DeveloperError} geometry must have attribute matching the attributeName argument.
  1001. * @exception {DeveloperError} The attribute componentDatatype must be ComponentDatatype.DOUBLE.
  1002. *
  1003. * @example
  1004. * geometry = Cesium.GeometryPipeline.encodeAttribute(geometry, 'position3D', 'position3DHigh', 'position3DLow');
  1005. */
  1006. GeometryPipeline.encodeAttribute = function (
  1007. geometry,
  1008. attributeName,
  1009. attributeHighName,
  1010. attributeLowName
  1011. ) {
  1012. //>>includeStart('debug', pragmas.debug);
  1013. if (!when.defined(geometry)) {
  1014. throw new Check.DeveloperError("geometry is required.");
  1015. }
  1016. if (!when.defined(attributeName)) {
  1017. throw new Check.DeveloperError("attributeName is required.");
  1018. }
  1019. if (!when.defined(attributeHighName)) {
  1020. throw new Check.DeveloperError("attributeHighName is required.");
  1021. }
  1022. if (!when.defined(attributeLowName)) {
  1023. throw new Check.DeveloperError("attributeLowName is required.");
  1024. }
  1025. if (!when.defined(geometry.attributes[attributeName])) {
  1026. throw new Check.DeveloperError(
  1027. "geometry must have attribute matching the attributeName argument: " +
  1028. attributeName +
  1029. "."
  1030. );
  1031. }
  1032. if (
  1033. geometry.attributes[attributeName].componentDatatype !==
  1034. ComponentDatatype.ComponentDatatype.DOUBLE
  1035. ) {
  1036. throw new Check.DeveloperError(
  1037. "The attribute componentDatatype must be ComponentDatatype.DOUBLE."
  1038. );
  1039. }
  1040. //>>includeEnd('debug');
  1041. var attribute = geometry.attributes[attributeName];
  1042. var values = attribute.values;
  1043. var length = values.length;
  1044. var highValues = new Float32Array(length);
  1045. var lowValues = new Float32Array(length);
  1046. for (var i = 0; i < length; ++i) {
  1047. EncodedCartesian3.EncodedCartesian3.encode(values[i], encodedResult);
  1048. highValues[i] = encodedResult.high;
  1049. lowValues[i] = encodedResult.low;
  1050. }
  1051. var componentsPerAttribute = attribute.componentsPerAttribute;
  1052. geometry.attributes[attributeHighName] = new GeometryAttribute.GeometryAttribute({
  1053. componentDatatype: ComponentDatatype.ComponentDatatype.FLOAT,
  1054. componentsPerAttribute: componentsPerAttribute,
  1055. values: highValues,
  1056. });
  1057. geometry.attributes[attributeLowName] = new GeometryAttribute.GeometryAttribute({
  1058. componentDatatype: ComponentDatatype.ComponentDatatype.FLOAT,
  1059. componentsPerAttribute: componentsPerAttribute,
  1060. values: lowValues,
  1061. });
  1062. delete geometry.attributes[attributeName];
  1063. return geometry;
  1064. };
  1065. var scratchCartesian3$1 = new Cartesian2.Cartesian3();
  1066. function transformPoint(matrix, attribute) {
  1067. if (when.defined(attribute)) {
  1068. var values = attribute.values;
  1069. var length = values.length;
  1070. for (var i = 0; i < length; i += 3) {
  1071. Cartesian2.Cartesian3.unpack(values, i, scratchCartesian3$1);
  1072. Transforms.Matrix4.multiplyByPoint(matrix, scratchCartesian3$1, scratchCartesian3$1);
  1073. Cartesian2.Cartesian3.pack(scratchCartesian3$1, values, i);
  1074. }
  1075. }
  1076. }
  1077. function transformVector(matrix, attribute) {
  1078. if (when.defined(attribute)) {
  1079. var values = attribute.values;
  1080. var length = values.length;
  1081. for (var i = 0; i < length; i += 3) {
  1082. Cartesian2.Cartesian3.unpack(values, i, scratchCartesian3$1);
  1083. Transforms.Matrix3.multiplyByVector(matrix, scratchCartesian3$1, scratchCartesian3$1);
  1084. scratchCartesian3$1 = Cartesian2.Cartesian3.normalize(
  1085. scratchCartesian3$1,
  1086. scratchCartesian3$1
  1087. );
  1088. Cartesian2.Cartesian3.pack(scratchCartesian3$1, values, i);
  1089. }
  1090. }
  1091. }
  1092. var inverseTranspose = new Transforms.Matrix4();
  1093. var normalMatrix = new Transforms.Matrix3();
  1094. /**
  1095. * Transforms a geometry instance to world coordinates. This changes
  1096. * the instance's <code>modelMatrix</code> to {@link Matrix4.IDENTITY} and transforms the
  1097. * following attributes if they are present: <code>position</code>, <code>normal</code>,
  1098. * <code>tangent</code>, and <code>bitangent</code>.
  1099. *
  1100. * @param {GeometryInstance} instance The geometry instance to modify.
  1101. * @returns {GeometryInstance} The modified <code>instance</code> argument, with its attributes transforms to world coordinates.
  1102. *
  1103. * @example
  1104. * Cesium.GeometryPipeline.transformToWorldCoordinates(instance);
  1105. */
  1106. GeometryPipeline.transformToWorldCoordinates = function (instance) {
  1107. //>>includeStart('debug', pragmas.debug);
  1108. if (!when.defined(instance)) {
  1109. throw new Check.DeveloperError("instance is required.");
  1110. }
  1111. //>>includeEnd('debug');
  1112. var modelMatrix = instance.modelMatrix;
  1113. if (Transforms.Matrix4.equals(modelMatrix, Transforms.Matrix4.IDENTITY)) {
  1114. // Already in world coordinates
  1115. return instance;
  1116. }
  1117. var attributes = instance.geometry.attributes;
  1118. // Transform attributes in known vertex formats
  1119. transformPoint(modelMatrix, attributes.position);
  1120. transformPoint(modelMatrix, attributes.prevPosition);
  1121. transformPoint(modelMatrix, attributes.nextPosition);
  1122. if (
  1123. when.defined(attributes.normal) ||
  1124. when.defined(attributes.tangent) ||
  1125. when.defined(attributes.bitangent)
  1126. ) {
  1127. Transforms.Matrix4.inverse(modelMatrix, inverseTranspose);
  1128. Transforms.Matrix4.transpose(inverseTranspose, inverseTranspose);
  1129. Transforms.Matrix4.getMatrix3(inverseTranspose, normalMatrix);
  1130. transformVector(normalMatrix, attributes.normal);
  1131. transformVector(normalMatrix, attributes.tangent);
  1132. transformVector(normalMatrix, attributes.bitangent);
  1133. }
  1134. var boundingSphere = instance.geometry.boundingSphere;
  1135. if (when.defined(boundingSphere)) {
  1136. instance.geometry.boundingSphere = Transforms.BoundingSphere.transform(
  1137. boundingSphere,
  1138. modelMatrix,
  1139. boundingSphere
  1140. );
  1141. }
  1142. instance.modelMatrix = Transforms.Matrix4.clone(Transforms.Matrix4.IDENTITY);
  1143. return instance;
  1144. };
  1145. function findAttributesInAllGeometries(instances, propertyName) {
  1146. var length = instances.length;
  1147. var attributesInAllGeometries = {};
  1148. var attributes0 = instances[0][propertyName].attributes;
  1149. var name;
  1150. for (name in attributes0) {
  1151. if (
  1152. attributes0.hasOwnProperty(name) &&
  1153. when.defined(attributes0[name]) &&
  1154. when.defined(attributes0[name].values)
  1155. ) {
  1156. var attribute = attributes0[name];
  1157. var numberOfComponents = attribute.values.length;
  1158. var inAllGeometries = true;
  1159. // Does this same attribute exist in all geometries?
  1160. for (var i = 1; i < length; ++i) {
  1161. var otherAttribute = instances[i][propertyName].attributes[name];
  1162. if (
  1163. !when.defined(otherAttribute) ||
  1164. attribute.componentDatatype !== otherAttribute.componentDatatype ||
  1165. attribute.componentsPerAttribute !==
  1166. otherAttribute.componentsPerAttribute ||
  1167. attribute.normalize !== otherAttribute.normalize
  1168. ) {
  1169. inAllGeometries = false;
  1170. break;
  1171. }
  1172. numberOfComponents += otherAttribute.values.length;
  1173. }
  1174. if (inAllGeometries) {
  1175. attributesInAllGeometries[name] = new GeometryAttribute.GeometryAttribute({
  1176. componentDatatype: attribute.componentDatatype,
  1177. componentsPerAttribute: attribute.componentsPerAttribute,
  1178. normalize: attribute.normalize,
  1179. values: ComponentDatatype.ComponentDatatype.createTypedArray(
  1180. attribute.componentDatatype,
  1181. numberOfComponents
  1182. ),
  1183. });
  1184. }
  1185. }
  1186. }
  1187. return attributesInAllGeometries;
  1188. }
  1189. var tempScratch = new Cartesian2.Cartesian3();
  1190. function combineGeometries(instances, propertyName) {
  1191. var length = instances.length;
  1192. var name;
  1193. var i;
  1194. var j;
  1195. var k;
  1196. var m = instances[0].modelMatrix;
  1197. var haveIndices = when.defined(instances[0][propertyName].indices);
  1198. var primitiveType = instances[0][propertyName].primitiveType;
  1199. //>>includeStart('debug', pragmas.debug);
  1200. for (i = 1; i < length; ++i) {
  1201. if (!Transforms.Matrix4.equals(instances[i].modelMatrix, m)) {
  1202. throw new Check.DeveloperError("All instances must have the same modelMatrix.");
  1203. }
  1204. if (when.defined(instances[i][propertyName].indices) !== haveIndices) {
  1205. throw new Check.DeveloperError(
  1206. "All instance geometries must have an indices or not have one."
  1207. );
  1208. }
  1209. if (instances[i][propertyName].primitiveType !== primitiveType) {
  1210. throw new Check.DeveloperError(
  1211. "All instance geometries must have the same primitiveType."
  1212. );
  1213. }
  1214. }
  1215. //>>includeEnd('debug');
  1216. // Find subset of attributes in all geometries
  1217. var attributes = findAttributesInAllGeometries(instances, propertyName);
  1218. var values;
  1219. var sourceValues;
  1220. var sourceValuesLength;
  1221. // Combine attributes from each geometry into a single typed array
  1222. for (name in attributes) {
  1223. if (attributes.hasOwnProperty(name)) {
  1224. values = attributes[name].values;
  1225. k = 0;
  1226. for (i = 0; i < length; ++i) {
  1227. sourceValues = instances[i][propertyName].attributes[name].values;
  1228. sourceValuesLength = sourceValues.length;
  1229. for (j = 0; j < sourceValuesLength; ++j) {
  1230. values[k++] = sourceValues[j];
  1231. }
  1232. }
  1233. }
  1234. }
  1235. // Combine index lists
  1236. var indices;
  1237. if (haveIndices) {
  1238. var numberOfIndices = 0;
  1239. for (i = 0; i < length; ++i) {
  1240. numberOfIndices += instances[i][propertyName].indices.length;
  1241. }
  1242. var numberOfVertices = GeometryAttribute.Geometry.computeNumberOfVertices(
  1243. new GeometryAttribute.Geometry({
  1244. attributes: attributes,
  1245. primitiveType: GeometryAttribute.PrimitiveType.POINTS,
  1246. })
  1247. );
  1248. var destIndices = IndexDatatype.IndexDatatype.createTypedArray(
  1249. numberOfVertices,
  1250. numberOfIndices
  1251. );
  1252. var destOffset = 0;
  1253. var offset = 0;
  1254. for (i = 0; i < length; ++i) {
  1255. var sourceIndices = instances[i][propertyName].indices;
  1256. var sourceIndicesLen = sourceIndices.length;
  1257. for (k = 0; k < sourceIndicesLen; ++k) {
  1258. destIndices[destOffset++] = offset + sourceIndices[k];
  1259. }
  1260. offset += GeometryAttribute.Geometry.computeNumberOfVertices(instances[i][propertyName]);
  1261. }
  1262. indices = destIndices;
  1263. }
  1264. // Create bounding sphere that includes all instances
  1265. var center = new Cartesian2.Cartesian3();
  1266. var radius = 0.0;
  1267. var bs;
  1268. for (i = 0; i < length; ++i) {
  1269. bs = instances[i][propertyName].boundingSphere;
  1270. if (!when.defined(bs)) {
  1271. // If any geometries have an undefined bounding sphere, then so does the combined geometry
  1272. center = undefined;
  1273. break;
  1274. }
  1275. Cartesian2.Cartesian3.add(bs.center, center, center);
  1276. }
  1277. if (when.defined(center)) {
  1278. Cartesian2.Cartesian3.divideByScalar(center, length, center);
  1279. for (i = 0; i < length; ++i) {
  1280. bs = instances[i][propertyName].boundingSphere;
  1281. var tempRadius =
  1282. Cartesian2.Cartesian3.magnitude(
  1283. Cartesian2.Cartesian3.subtract(bs.center, center, tempScratch)
  1284. ) + bs.radius;
  1285. if (tempRadius > radius) {
  1286. radius = tempRadius;
  1287. }
  1288. }
  1289. }
  1290. return new GeometryAttribute.Geometry({
  1291. attributes: attributes,
  1292. indices: indices,
  1293. primitiveType: primitiveType,
  1294. boundingSphere: when.defined(center)
  1295. ? new Transforms.BoundingSphere(center, radius)
  1296. : undefined,
  1297. });
  1298. }
  1299. /**
  1300. * Combines geometry from several {@link GeometryInstance} objects into one geometry.
  1301. * This concatenates the attributes, concatenates and adjusts the indices, and creates
  1302. * a bounding sphere encompassing all instances.
  1303. * <p>
  1304. * If the instances do not have the same attributes, a subset of attributes common
  1305. * to all instances is used, and the others are ignored.
  1306. * </p>
  1307. * <p>
  1308. * This is used by {@link Primitive} to efficiently render a large amount of static data.
  1309. * </p>
  1310. *
  1311. * @private
  1312. *
  1313. * @param {GeometryInstance[]} [instances] The array of {@link GeometryInstance} objects whose geometry will be combined.
  1314. * @returns {Geometry} A single geometry created from the provided geometry instances.
  1315. *
  1316. * @exception {DeveloperError} All instances must have the same modelMatrix.
  1317. * @exception {DeveloperError} All instance geometries must have an indices or not have one.
  1318. * @exception {DeveloperError} All instance geometries must have the same primitiveType.
  1319. *
  1320. *
  1321. * @example
  1322. * for (var i = 0; i < instances.length; ++i) {
  1323. * Cesium.GeometryPipeline.transformToWorldCoordinates(instances[i]);
  1324. * }
  1325. * var geometries = Cesium.GeometryPipeline.combineInstances(instances);
  1326. *
  1327. * @see GeometryPipeline.transformToWorldCoordinates
  1328. */
  1329. GeometryPipeline.combineInstances = function (instances) {
  1330. //>>includeStart('debug', pragmas.debug);
  1331. if (!when.defined(instances) || instances.length < 1) {
  1332. throw new Check.DeveloperError(
  1333. "instances is required and must have length greater than zero."
  1334. );
  1335. }
  1336. //>>includeEnd('debug');
  1337. var instanceGeometry = [];
  1338. var instanceSplitGeometry = [];
  1339. var length = instances.length;
  1340. for (var i = 0; i < length; ++i) {
  1341. var instance = instances[i];
  1342. if (when.defined(instance.geometry)) {
  1343. instanceGeometry.push(instance);
  1344. } else if (
  1345. when.defined(instance.westHemisphereGeometry) &&
  1346. when.defined(instance.eastHemisphereGeometry)
  1347. ) {
  1348. instanceSplitGeometry.push(instance);
  1349. }
  1350. }
  1351. var geometries = [];
  1352. if (instanceGeometry.length > 0) {
  1353. geometries.push(combineGeometries(instanceGeometry, "geometry"));
  1354. }
  1355. if (instanceSplitGeometry.length > 0) {
  1356. geometries.push(
  1357. combineGeometries(instanceSplitGeometry, "westHemisphereGeometry")
  1358. );
  1359. geometries.push(
  1360. combineGeometries(instanceSplitGeometry, "eastHemisphereGeometry")
  1361. );
  1362. }
  1363. return geometries;
  1364. };
  1365. var normal = new Cartesian2.Cartesian3();
  1366. var v0 = new Cartesian2.Cartesian3();
  1367. var v1 = new Cartesian2.Cartesian3();
  1368. var v2 = new Cartesian2.Cartesian3();
  1369. /**
  1370. * Computes per-vertex normals for a geometry containing <code>TRIANGLES</code> by averaging the normals of
  1371. * all triangles incident to the vertex. The result is a new <code>normal</code> attribute added to the geometry.
  1372. * This assumes a counter-clockwise winding order.
  1373. *
  1374. * @param {Geometry} geometry The geometry to modify.
  1375. * @returns {Geometry} The modified <code>geometry</code> argument with the computed <code>normal</code> attribute.
  1376. *
  1377. * @exception {DeveloperError} geometry.indices length must be greater than 0 and be a multiple of 3.
  1378. * @exception {DeveloperError} geometry.primitiveType must be {@link PrimitiveType.TRIANGLES}.
  1379. *
  1380. * @example
  1381. * Cesium.GeometryPipeline.computeNormal(geometry);
  1382. */
  1383. GeometryPipeline.computeNormal = function (geometry) {
  1384. //>>includeStart('debug', pragmas.debug);
  1385. if (!when.defined(geometry)) {
  1386. throw new Check.DeveloperError("geometry is required.");
  1387. }
  1388. if (
  1389. !when.defined(geometry.attributes.position) ||
  1390. !when.defined(geometry.attributes.position.values)
  1391. ) {
  1392. throw new Check.DeveloperError(
  1393. "geometry.attributes.position.values is required."
  1394. );
  1395. }
  1396. if (!when.defined(geometry.indices)) {
  1397. throw new Check.DeveloperError("geometry.indices is required.");
  1398. }
  1399. if (geometry.indices.length < 2 || geometry.indices.length % 3 !== 0) {
  1400. throw new Check.DeveloperError(
  1401. "geometry.indices length must be greater than 0 and be a multiple of 3."
  1402. );
  1403. }
  1404. if (geometry.primitiveType !== GeometryAttribute.PrimitiveType.TRIANGLES) {
  1405. throw new Check.DeveloperError(
  1406. "geometry.primitiveType must be PrimitiveType.TRIANGLES."
  1407. );
  1408. }
  1409. //>>includeEnd('debug');
  1410. var indices = geometry.indices;
  1411. var attributes = geometry.attributes;
  1412. var vertices = attributes.position.values;
  1413. var numVertices = attributes.position.values.length / 3;
  1414. var numIndices = indices.length;
  1415. var normalsPerVertex = new Array(numVertices);
  1416. var normalsPerTriangle = new Array(numIndices / 3);
  1417. var normalIndices = new Array(numIndices);
  1418. var i;
  1419. for (i = 0; i < numVertices; i++) {
  1420. normalsPerVertex[i] = {
  1421. indexOffset: 0,
  1422. count: 0,
  1423. currentCount: 0,
  1424. };
  1425. }
  1426. var j = 0;
  1427. for (i = 0; i < numIndices; i += 3) {
  1428. var i0 = indices[i];
  1429. var i1 = indices[i + 1];
  1430. var i2 = indices[i + 2];
  1431. var i03 = i0 * 3;
  1432. var i13 = i1 * 3;
  1433. var i23 = i2 * 3;
  1434. v0.x = vertices[i03];
  1435. v0.y = vertices[i03 + 1];
  1436. v0.z = vertices[i03 + 2];
  1437. v1.x = vertices[i13];
  1438. v1.y = vertices[i13 + 1];
  1439. v1.z = vertices[i13 + 2];
  1440. v2.x = vertices[i23];
  1441. v2.y = vertices[i23 + 1];
  1442. v2.z = vertices[i23 + 2];
  1443. normalsPerVertex[i0].count++;
  1444. normalsPerVertex[i1].count++;
  1445. normalsPerVertex[i2].count++;
  1446. Cartesian2.Cartesian3.subtract(v1, v0, v1);
  1447. Cartesian2.Cartesian3.subtract(v2, v0, v2);
  1448. normalsPerTriangle[j] = Cartesian2.Cartesian3.cross(v1, v2, new Cartesian2.Cartesian3());
  1449. j++;
  1450. }
  1451. var indexOffset = 0;
  1452. for (i = 0; i < numVertices; i++) {
  1453. normalsPerVertex[i].indexOffset += indexOffset;
  1454. indexOffset += normalsPerVertex[i].count;
  1455. }
  1456. j = 0;
  1457. var vertexNormalData;
  1458. for (i = 0; i < numIndices; i += 3) {
  1459. vertexNormalData = normalsPerVertex[indices[i]];
  1460. var index = vertexNormalData.indexOffset + vertexNormalData.currentCount;
  1461. normalIndices[index] = j;
  1462. vertexNormalData.currentCount++;
  1463. vertexNormalData = normalsPerVertex[indices[i + 1]];
  1464. index = vertexNormalData.indexOffset + vertexNormalData.currentCount;
  1465. normalIndices[index] = j;
  1466. vertexNormalData.currentCount++;
  1467. vertexNormalData = normalsPerVertex[indices[i + 2]];
  1468. index = vertexNormalData.indexOffset + vertexNormalData.currentCount;
  1469. normalIndices[index] = j;
  1470. vertexNormalData.currentCount++;
  1471. j++;
  1472. }
  1473. var normalValues = new Float32Array(numVertices * 3);
  1474. for (i = 0; i < numVertices; i++) {
  1475. var i3 = i * 3;
  1476. vertexNormalData = normalsPerVertex[i];
  1477. Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.ZERO, normal);
  1478. if (vertexNormalData.count > 0) {
  1479. for (j = 0; j < vertexNormalData.count; j++) {
  1480. Cartesian2.Cartesian3.add(
  1481. normal,
  1482. normalsPerTriangle[normalIndices[vertexNormalData.indexOffset + j]],
  1483. normal
  1484. );
  1485. }
  1486. // We can run into an issue where a vertex is used with 2 primitives that have opposite winding order.
  1487. if (
  1488. Cartesian2.Cartesian3.equalsEpsilon(Cartesian2.Cartesian3.ZERO, normal, _Math.CesiumMath.EPSILON10)
  1489. ) {
  1490. Cartesian2.Cartesian3.clone(
  1491. normalsPerTriangle[normalIndices[vertexNormalData.indexOffset]],
  1492. normal
  1493. );
  1494. }
  1495. }
  1496. // We end up with a zero vector probably because of a degenerate triangle
  1497. if (
  1498. Cartesian2.Cartesian3.equalsEpsilon(Cartesian2.Cartesian3.ZERO, normal, _Math.CesiumMath.EPSILON10)
  1499. ) {
  1500. // Default to (0,0,1)
  1501. normal.z = 1.0;
  1502. }
  1503. Cartesian2.Cartesian3.normalize(normal, normal);
  1504. normalValues[i3] = normal.x;
  1505. normalValues[i3 + 1] = normal.y;
  1506. normalValues[i3 + 2] = normal.z;
  1507. }
  1508. geometry.attributes.normal = new GeometryAttribute.GeometryAttribute({
  1509. componentDatatype: ComponentDatatype.ComponentDatatype.FLOAT,
  1510. componentsPerAttribute: 3,
  1511. values: normalValues,
  1512. });
  1513. return geometry;
  1514. };
  1515. var normalScratch = new Cartesian2.Cartesian3();
  1516. var normalScale = new Cartesian2.Cartesian3();
  1517. var tScratch = new Cartesian2.Cartesian3();
  1518. /**
  1519. * Computes per-vertex tangents and bitangents for a geometry containing <code>TRIANGLES</code>.
  1520. * The result is new <code>tangent</code> and <code>bitangent</code> attributes added to the geometry.
  1521. * This assumes a counter-clockwise winding order.
  1522. * <p>
  1523. * Based on <a href="http://www.terathon.com/code/tangent.html">Computing Tangent Space Basis Vectors
  1524. * for an Arbitrary Mesh</a> by Eric Lengyel.
  1525. * </p>
  1526. *
  1527. * @param {Geometry} geometry The geometry to modify.
  1528. * @returns {Geometry} The modified <code>geometry</code> argument with the computed <code>tangent</code> and <code>bitangent</code> attributes.
  1529. *
  1530. * @exception {DeveloperError} geometry.indices length must be greater than 0 and be a multiple of 3.
  1531. * @exception {DeveloperError} geometry.primitiveType must be {@link PrimitiveType.TRIANGLES}.
  1532. *
  1533. * @example
  1534. * Cesium.GeometryPipeline.computeTangentAndBiTangent(geometry);
  1535. */
  1536. GeometryPipeline.computeTangentAndBitangent = function (geometry) {
  1537. //>>includeStart('debug', pragmas.debug);
  1538. if (!when.defined(geometry)) {
  1539. throw new Check.DeveloperError("geometry is required.");
  1540. }
  1541. //>>includeEnd('debug');
  1542. var attributes = geometry.attributes;
  1543. var indices = geometry.indices;
  1544. //>>includeStart('debug', pragmas.debug);
  1545. if (!when.defined(attributes.position) || !when.defined(attributes.position.values)) {
  1546. throw new Check.DeveloperError(
  1547. "geometry.attributes.position.values is required."
  1548. );
  1549. }
  1550. if (!when.defined(attributes.normal) || !when.defined(attributes.normal.values)) {
  1551. throw new Check.DeveloperError("geometry.attributes.normal.values is required.");
  1552. }
  1553. if (!when.defined(attributes.st) || !when.defined(attributes.st.values)) {
  1554. throw new Check.DeveloperError("geometry.attributes.st.values is required.");
  1555. }
  1556. if (!when.defined(indices)) {
  1557. throw new Check.DeveloperError("geometry.indices is required.");
  1558. }
  1559. if (indices.length < 2 || indices.length % 3 !== 0) {
  1560. throw new Check.DeveloperError(
  1561. "geometry.indices length must be greater than 0 and be a multiple of 3."
  1562. );
  1563. }
  1564. if (geometry.primitiveType !== GeometryAttribute.PrimitiveType.TRIANGLES) {
  1565. throw new Check.DeveloperError(
  1566. "geometry.primitiveType must be PrimitiveType.TRIANGLES."
  1567. );
  1568. }
  1569. //>>includeEnd('debug');
  1570. var vertices = geometry.attributes.position.values;
  1571. var normals = geometry.attributes.normal.values;
  1572. var st = geometry.attributes.st.values;
  1573. var numVertices = geometry.attributes.position.values.length / 3;
  1574. var numIndices = indices.length;
  1575. var tan1 = new Array(numVertices * 3);
  1576. var i;
  1577. for (i = 0; i < tan1.length; i++) {
  1578. tan1[i] = 0;
  1579. }
  1580. var i03;
  1581. var i13;
  1582. var i23;
  1583. for (i = 0; i < numIndices; i += 3) {
  1584. var i0 = indices[i];
  1585. var i1 = indices[i + 1];
  1586. var i2 = indices[i + 2];
  1587. i03 = i0 * 3;
  1588. i13 = i1 * 3;
  1589. i23 = i2 * 3;
  1590. var i02 = i0 * 2;
  1591. var i12 = i1 * 2;
  1592. var i22 = i2 * 2;
  1593. var ux = vertices[i03];
  1594. var uy = vertices[i03 + 1];
  1595. var uz = vertices[i03 + 2];
  1596. var wx = st[i02];
  1597. var wy = st[i02 + 1];
  1598. var t1 = st[i12 + 1] - wy;
  1599. var t2 = st[i22 + 1] - wy;
  1600. var r = 1.0 / ((st[i12] - wx) * t2 - (st[i22] - wx) * t1);
  1601. var sdirx = (t2 * (vertices[i13] - ux) - t1 * (vertices[i23] - ux)) * r;
  1602. var sdiry =
  1603. (t2 * (vertices[i13 + 1] - uy) - t1 * (vertices[i23 + 1] - uy)) * r;
  1604. var sdirz =
  1605. (t2 * (vertices[i13 + 2] - uz) - t1 * (vertices[i23 + 2] - uz)) * r;
  1606. tan1[i03] += sdirx;
  1607. tan1[i03 + 1] += sdiry;
  1608. tan1[i03 + 2] += sdirz;
  1609. tan1[i13] += sdirx;
  1610. tan1[i13 + 1] += sdiry;
  1611. tan1[i13 + 2] += sdirz;
  1612. tan1[i23] += sdirx;
  1613. tan1[i23 + 1] += sdiry;
  1614. tan1[i23 + 2] += sdirz;
  1615. }
  1616. var tangentValues = new Float32Array(numVertices * 3);
  1617. var bitangentValues = new Float32Array(numVertices * 3);
  1618. for (i = 0; i < numVertices; i++) {
  1619. i03 = i * 3;
  1620. i13 = i03 + 1;
  1621. i23 = i03 + 2;
  1622. var n = Cartesian2.Cartesian3.fromArray(normals, i03, normalScratch);
  1623. var t = Cartesian2.Cartesian3.fromArray(tan1, i03, tScratch);
  1624. var scalar = Cartesian2.Cartesian3.dot(n, t);
  1625. Cartesian2.Cartesian3.multiplyByScalar(n, scalar, normalScale);
  1626. Cartesian2.Cartesian3.normalize(Cartesian2.Cartesian3.subtract(t, normalScale, t), t);
  1627. tangentValues[i03] = t.x;
  1628. tangentValues[i13] = t.y;
  1629. tangentValues[i23] = t.z;
  1630. Cartesian2.Cartesian3.normalize(Cartesian2.Cartesian3.cross(n, t, t), t);
  1631. bitangentValues[i03] = t.x;
  1632. bitangentValues[i13] = t.y;
  1633. bitangentValues[i23] = t.z;
  1634. }
  1635. geometry.attributes.tangent = new GeometryAttribute.GeometryAttribute({
  1636. componentDatatype: ComponentDatatype.ComponentDatatype.FLOAT,
  1637. componentsPerAttribute: 3,
  1638. values: tangentValues,
  1639. });
  1640. geometry.attributes.bitangent = new GeometryAttribute.GeometryAttribute({
  1641. componentDatatype: ComponentDatatype.ComponentDatatype.FLOAT,
  1642. componentsPerAttribute: 3,
  1643. values: bitangentValues,
  1644. });
  1645. return geometry;
  1646. };
  1647. var scratchCartesian2$1 = new Cartesian2.Cartesian2();
  1648. var toEncode1 = new Cartesian2.Cartesian3();
  1649. var toEncode2 = new Cartesian2.Cartesian3();
  1650. var toEncode3 = new Cartesian2.Cartesian3();
  1651. var encodeResult2 = new Cartesian2.Cartesian2();
  1652. /**
  1653. * Compresses and packs geometry normal attribute values to save memory.
  1654. *
  1655. * @param {Geometry} geometry The geometry to modify.
  1656. * @returns {Geometry} The modified <code>geometry</code> argument, with its normals compressed and packed.
  1657. *
  1658. * @example
  1659. * geometry = Cesium.GeometryPipeline.compressVertices(geometry);
  1660. */
  1661. GeometryPipeline.compressVertices = function (geometry) {
  1662. //>>includeStart('debug', pragmas.debug);
  1663. if (!when.defined(geometry)) {
  1664. throw new Check.DeveloperError("geometry is required.");
  1665. }
  1666. //>>includeEnd('debug');
  1667. var extrudeAttribute = geometry.attributes.extrudeDirection;
  1668. var i;
  1669. var numVertices;
  1670. if (when.defined(extrudeAttribute)) {
  1671. //only shadow volumes use extrudeDirection, and shadow volumes use vertexFormat: POSITION_ONLY so we don't need to check other attributes
  1672. var extrudeDirections = extrudeAttribute.values;
  1673. numVertices = extrudeDirections.length / 3.0;
  1674. var compressedDirections = new Float32Array(numVertices * 2);
  1675. var i2 = 0;
  1676. for (i = 0; i < numVertices; ++i) {
  1677. Cartesian2.Cartesian3.fromArray(extrudeDirections, i * 3.0, toEncode1);
  1678. if (Cartesian2.Cartesian3.equals(toEncode1, Cartesian2.Cartesian3.ZERO)) {
  1679. i2 += 2;
  1680. continue;
  1681. }
  1682. encodeResult2 = AttributeCompression.AttributeCompression.octEncodeInRange(
  1683. toEncode1,
  1684. 65535,
  1685. encodeResult2
  1686. );
  1687. compressedDirections[i2++] = encodeResult2.x;
  1688. compressedDirections[i2++] = encodeResult2.y;
  1689. }
  1690. geometry.attributes.compressedAttributes = new GeometryAttribute.GeometryAttribute({
  1691. componentDatatype: ComponentDatatype.ComponentDatatype.FLOAT,
  1692. componentsPerAttribute: 2,
  1693. values: compressedDirections,
  1694. });
  1695. delete geometry.attributes.extrudeDirection;
  1696. return geometry;
  1697. }
  1698. var normalAttribute = geometry.attributes.normal;
  1699. var stAttribute = geometry.attributes.st;
  1700. var hasNormal = when.defined(normalAttribute);
  1701. var hasSt = when.defined(stAttribute);
  1702. if (!hasNormal && !hasSt) {
  1703. return geometry;
  1704. }
  1705. var tangentAttribute = geometry.attributes.tangent;
  1706. var bitangentAttribute = geometry.attributes.bitangent;
  1707. var hasTangent = when.defined(tangentAttribute);
  1708. var hasBitangent = when.defined(bitangentAttribute);
  1709. var normals;
  1710. var st;
  1711. var tangents;
  1712. var bitangents;
  1713. if (hasNormal) {
  1714. normals = normalAttribute.values;
  1715. }
  1716. if (hasSt) {
  1717. st = stAttribute.values;
  1718. }
  1719. if (hasTangent) {
  1720. tangents = tangentAttribute.values;
  1721. }
  1722. if (hasBitangent) {
  1723. bitangents = bitangentAttribute.values;
  1724. }
  1725. var length = hasNormal ? normals.length : st.length;
  1726. var numComponents = hasNormal ? 3.0 : 2.0;
  1727. numVertices = length / numComponents;
  1728. var compressedLength = numVertices;
  1729. var numCompressedComponents = hasSt && hasNormal ? 2.0 : 1.0;
  1730. numCompressedComponents += hasTangent || hasBitangent ? 1.0 : 0.0;
  1731. compressedLength *= numCompressedComponents;
  1732. var compressedAttributes = new Float32Array(compressedLength);
  1733. var normalIndex = 0;
  1734. for (i = 0; i < numVertices; ++i) {
  1735. if (hasSt) {
  1736. Cartesian2.Cartesian2.fromArray(st, i * 2.0, scratchCartesian2$1);
  1737. compressedAttributes[
  1738. normalIndex++
  1739. ] = AttributeCompression.AttributeCompression.compressTextureCoordinates(scratchCartesian2$1);
  1740. }
  1741. var index = i * 3.0;
  1742. if (hasNormal && when.defined(tangents) && when.defined(bitangents)) {
  1743. Cartesian2.Cartesian3.fromArray(normals, index, toEncode1);
  1744. Cartesian2.Cartesian3.fromArray(tangents, index, toEncode2);
  1745. Cartesian2.Cartesian3.fromArray(bitangents, index, toEncode3);
  1746. AttributeCompression.AttributeCompression.octPack(
  1747. toEncode1,
  1748. toEncode2,
  1749. toEncode3,
  1750. scratchCartesian2$1
  1751. );
  1752. compressedAttributes[normalIndex++] = scratchCartesian2$1.x;
  1753. compressedAttributes[normalIndex++] = scratchCartesian2$1.y;
  1754. } else {
  1755. if (hasNormal) {
  1756. Cartesian2.Cartesian3.fromArray(normals, index, toEncode1);
  1757. compressedAttributes[
  1758. normalIndex++
  1759. ] = AttributeCompression.AttributeCompression.octEncodeFloat(toEncode1);
  1760. }
  1761. if (hasTangent) {
  1762. Cartesian2.Cartesian3.fromArray(tangents, index, toEncode1);
  1763. compressedAttributes[
  1764. normalIndex++
  1765. ] = AttributeCompression.AttributeCompression.octEncodeFloat(toEncode1);
  1766. }
  1767. if (hasBitangent) {
  1768. Cartesian2.Cartesian3.fromArray(bitangents, index, toEncode1);
  1769. compressedAttributes[
  1770. normalIndex++
  1771. ] = AttributeCompression.AttributeCompression.octEncodeFloat(toEncode1);
  1772. }
  1773. }
  1774. }
  1775. geometry.attributes.compressedAttributes = new GeometryAttribute.GeometryAttribute({
  1776. componentDatatype: ComponentDatatype.ComponentDatatype.FLOAT,
  1777. componentsPerAttribute: numCompressedComponents,
  1778. values: compressedAttributes,
  1779. });
  1780. if (hasNormal) {
  1781. delete geometry.attributes.normal;
  1782. }
  1783. if (hasSt) {
  1784. delete geometry.attributes.st;
  1785. }
  1786. if (hasBitangent) {
  1787. delete geometry.attributes.bitangent;
  1788. }
  1789. if (hasTangent) {
  1790. delete geometry.attributes.tangent;
  1791. }
  1792. return geometry;
  1793. };
  1794. function indexTriangles(geometry) {
  1795. if (when.defined(geometry.indices)) {
  1796. return geometry;
  1797. }
  1798. var numberOfVertices = GeometryAttribute.Geometry.computeNumberOfVertices(geometry);
  1799. //>>includeStart('debug', pragmas.debug);
  1800. if (numberOfVertices < 3) {
  1801. throw new Check.DeveloperError("The number of vertices must be at least three.");
  1802. }
  1803. if (numberOfVertices % 3 !== 0) {
  1804. throw new Check.DeveloperError(
  1805. "The number of vertices must be a multiple of three."
  1806. );
  1807. }
  1808. //>>includeEnd('debug');
  1809. var indices = IndexDatatype.IndexDatatype.createTypedArray(
  1810. numberOfVertices,
  1811. numberOfVertices
  1812. );
  1813. for (var i = 0; i < numberOfVertices; ++i) {
  1814. indices[i] = i;
  1815. }
  1816. geometry.indices = indices;
  1817. return geometry;
  1818. }
  1819. function indexTriangleFan(geometry) {
  1820. var numberOfVertices = GeometryAttribute.Geometry.computeNumberOfVertices(geometry);
  1821. //>>includeStart('debug', pragmas.debug);
  1822. if (numberOfVertices < 3) {
  1823. throw new Check.DeveloperError("The number of vertices must be at least three.");
  1824. }
  1825. //>>includeEnd('debug');
  1826. var indices = IndexDatatype.IndexDatatype.createTypedArray(
  1827. numberOfVertices,
  1828. (numberOfVertices - 2) * 3
  1829. );
  1830. indices[0] = 1;
  1831. indices[1] = 0;
  1832. indices[2] = 2;
  1833. var indicesIndex = 3;
  1834. for (var i = 3; i < numberOfVertices; ++i) {
  1835. indices[indicesIndex++] = i - 1;
  1836. indices[indicesIndex++] = 0;
  1837. indices[indicesIndex++] = i;
  1838. }
  1839. geometry.indices = indices;
  1840. geometry.primitiveType = GeometryAttribute.PrimitiveType.TRIANGLES;
  1841. return geometry;
  1842. }
  1843. function indexTriangleStrip(geometry) {
  1844. var numberOfVertices = GeometryAttribute.Geometry.computeNumberOfVertices(geometry);
  1845. //>>includeStart('debug', pragmas.debug);
  1846. if (numberOfVertices < 3) {
  1847. throw new Check.DeveloperError("The number of vertices must be at least 3.");
  1848. }
  1849. //>>includeEnd('debug');
  1850. var indices = IndexDatatype.IndexDatatype.createTypedArray(
  1851. numberOfVertices,
  1852. (numberOfVertices - 2) * 3
  1853. );
  1854. indices[0] = 0;
  1855. indices[1] = 1;
  1856. indices[2] = 2;
  1857. if (numberOfVertices > 3) {
  1858. indices[3] = 0;
  1859. indices[4] = 2;
  1860. indices[5] = 3;
  1861. }
  1862. var indicesIndex = 6;
  1863. for (var i = 3; i < numberOfVertices - 1; i += 2) {
  1864. indices[indicesIndex++] = i;
  1865. indices[indicesIndex++] = i - 1;
  1866. indices[indicesIndex++] = i + 1;
  1867. if (i + 2 < numberOfVertices) {
  1868. indices[indicesIndex++] = i;
  1869. indices[indicesIndex++] = i + 1;
  1870. indices[indicesIndex++] = i + 2;
  1871. }
  1872. }
  1873. geometry.indices = indices;
  1874. geometry.primitiveType = GeometryAttribute.PrimitiveType.TRIANGLES;
  1875. return geometry;
  1876. }
  1877. function indexLines(geometry) {
  1878. if (when.defined(geometry.indices)) {
  1879. return geometry;
  1880. }
  1881. var numberOfVertices = GeometryAttribute.Geometry.computeNumberOfVertices(geometry);
  1882. //>>includeStart('debug', pragmas.debug);
  1883. if (numberOfVertices < 2) {
  1884. throw new Check.DeveloperError("The number of vertices must be at least two.");
  1885. }
  1886. if (numberOfVertices % 2 !== 0) {
  1887. throw new Check.DeveloperError("The number of vertices must be a multiple of 2.");
  1888. }
  1889. //>>includeEnd('debug');
  1890. var indices = IndexDatatype.IndexDatatype.createTypedArray(
  1891. numberOfVertices,
  1892. numberOfVertices
  1893. );
  1894. for (var i = 0; i < numberOfVertices; ++i) {
  1895. indices[i] = i;
  1896. }
  1897. geometry.indices = indices;
  1898. return geometry;
  1899. }
  1900. function indexLineStrip(geometry) {
  1901. var numberOfVertices = GeometryAttribute.Geometry.computeNumberOfVertices(geometry);
  1902. //>>includeStart('debug', pragmas.debug);
  1903. if (numberOfVertices < 2) {
  1904. throw new Check.DeveloperError("The number of vertices must be at least two.");
  1905. }
  1906. //>>includeEnd('debug');
  1907. var indices = IndexDatatype.IndexDatatype.createTypedArray(
  1908. numberOfVertices,
  1909. (numberOfVertices - 1) * 2
  1910. );
  1911. indices[0] = 0;
  1912. indices[1] = 1;
  1913. var indicesIndex = 2;
  1914. for (var i = 2; i < numberOfVertices; ++i) {
  1915. indices[indicesIndex++] = i - 1;
  1916. indices[indicesIndex++] = i;
  1917. }
  1918. geometry.indices = indices;
  1919. geometry.primitiveType = GeometryAttribute.PrimitiveType.LINES;
  1920. return geometry;
  1921. }
  1922. function indexLineLoop(geometry) {
  1923. var numberOfVertices = GeometryAttribute.Geometry.computeNumberOfVertices(geometry);
  1924. //>>includeStart('debug', pragmas.debug);
  1925. if (numberOfVertices < 2) {
  1926. throw new Check.DeveloperError("The number of vertices must be at least two.");
  1927. }
  1928. //>>includeEnd('debug');
  1929. var indices = IndexDatatype.IndexDatatype.createTypedArray(
  1930. numberOfVertices,
  1931. numberOfVertices * 2
  1932. );
  1933. indices[0] = 0;
  1934. indices[1] = 1;
  1935. var indicesIndex = 2;
  1936. for (var i = 2; i < numberOfVertices; ++i) {
  1937. indices[indicesIndex++] = i - 1;
  1938. indices[indicesIndex++] = i;
  1939. }
  1940. indices[indicesIndex++] = numberOfVertices - 1;
  1941. indices[indicesIndex] = 0;
  1942. geometry.indices = indices;
  1943. geometry.primitiveType = GeometryAttribute.PrimitiveType.LINES;
  1944. return geometry;
  1945. }
  1946. function indexPrimitive(geometry) {
  1947. switch (geometry.primitiveType) {
  1948. case GeometryAttribute.PrimitiveType.TRIANGLE_FAN:
  1949. return indexTriangleFan(geometry);
  1950. case GeometryAttribute.PrimitiveType.TRIANGLE_STRIP:
  1951. return indexTriangleStrip(geometry);
  1952. case GeometryAttribute.PrimitiveType.TRIANGLES:
  1953. return indexTriangles(geometry);
  1954. case GeometryAttribute.PrimitiveType.LINE_STRIP:
  1955. return indexLineStrip(geometry);
  1956. case GeometryAttribute.PrimitiveType.LINE_LOOP:
  1957. return indexLineLoop(geometry);
  1958. case GeometryAttribute.PrimitiveType.LINES:
  1959. return indexLines(geometry);
  1960. }
  1961. return geometry;
  1962. }
  1963. function offsetPointFromXZPlane(p, isBehind) {
  1964. if (Math.abs(p.y) < _Math.CesiumMath.EPSILON6) {
  1965. if (isBehind) {
  1966. p.y = -_Math.CesiumMath.EPSILON6;
  1967. } else {
  1968. p.y = _Math.CesiumMath.EPSILON6;
  1969. }
  1970. }
  1971. }
  1972. function offsetTriangleFromXZPlane(p0, p1, p2) {
  1973. if (p0.y !== 0.0 && p1.y !== 0.0 && p2.y !== 0.0) {
  1974. offsetPointFromXZPlane(p0, p0.y < 0.0);
  1975. offsetPointFromXZPlane(p1, p1.y < 0.0);
  1976. offsetPointFromXZPlane(p2, p2.y < 0.0);
  1977. return;
  1978. }
  1979. var p0y = Math.abs(p0.y);
  1980. var p1y = Math.abs(p1.y);
  1981. var p2y = Math.abs(p2.y);
  1982. var sign;
  1983. if (p0y > p1y) {
  1984. if (p0y > p2y) {
  1985. sign = _Math.CesiumMath.sign(p0.y);
  1986. } else {
  1987. sign = _Math.CesiumMath.sign(p2.y);
  1988. }
  1989. } else if (p1y > p2y) {
  1990. sign = _Math.CesiumMath.sign(p1.y);
  1991. } else {
  1992. sign = _Math.CesiumMath.sign(p2.y);
  1993. }
  1994. var isBehind = sign < 0.0;
  1995. offsetPointFromXZPlane(p0, isBehind);
  1996. offsetPointFromXZPlane(p1, isBehind);
  1997. offsetPointFromXZPlane(p2, isBehind);
  1998. }
  1999. var c3 = new Cartesian2.Cartesian3();
  2000. function getXZIntersectionOffsetPoints(p, p1, u1, v1) {
  2001. Cartesian2.Cartesian3.add(
  2002. p,
  2003. Cartesian2.Cartesian3.multiplyByScalar(
  2004. Cartesian2.Cartesian3.subtract(p1, p, c3),
  2005. p.y / (p.y - p1.y),
  2006. c3
  2007. ),
  2008. u1
  2009. );
  2010. Cartesian2.Cartesian3.clone(u1, v1);
  2011. offsetPointFromXZPlane(u1, true);
  2012. offsetPointFromXZPlane(v1, false);
  2013. }
  2014. var u1 = new Cartesian2.Cartesian3();
  2015. var u2 = new Cartesian2.Cartesian3();
  2016. var q1 = new Cartesian2.Cartesian3();
  2017. var q2 = new Cartesian2.Cartesian3();
  2018. var splitTriangleResult = {
  2019. positions: new Array(7),
  2020. indices: new Array(3 * 3),
  2021. };
  2022. function splitTriangle(p0, p1, p2) {
  2023. // In WGS84 coordinates, for a triangle approximately on the
  2024. // ellipsoid to cross the IDL, first it needs to be on the
  2025. // negative side of the plane x = 0.
  2026. if (p0.x >= 0.0 || p1.x >= 0.0 || p2.x >= 0.0) {
  2027. return undefined;
  2028. }
  2029. offsetTriangleFromXZPlane(p0, p1, p2);
  2030. var p0Behind = p0.y < 0.0;
  2031. var p1Behind = p1.y < 0.0;
  2032. var p2Behind = p2.y < 0.0;
  2033. var numBehind = 0;
  2034. numBehind += p0Behind ? 1 : 0;
  2035. numBehind += p1Behind ? 1 : 0;
  2036. numBehind += p2Behind ? 1 : 0;
  2037. var indices = splitTriangleResult.indices;
  2038. if (numBehind === 1) {
  2039. indices[1] = 3;
  2040. indices[2] = 4;
  2041. indices[5] = 6;
  2042. indices[7] = 6;
  2043. indices[8] = 5;
  2044. if (p0Behind) {
  2045. getXZIntersectionOffsetPoints(p0, p1, u1, q1);
  2046. getXZIntersectionOffsetPoints(p0, p2, u2, q2);
  2047. indices[0] = 0;
  2048. indices[3] = 1;
  2049. indices[4] = 2;
  2050. indices[6] = 1;
  2051. } else if (p1Behind) {
  2052. getXZIntersectionOffsetPoints(p1, p2, u1, q1);
  2053. getXZIntersectionOffsetPoints(p1, p0, u2, q2);
  2054. indices[0] = 1;
  2055. indices[3] = 2;
  2056. indices[4] = 0;
  2057. indices[6] = 2;
  2058. } else if (p2Behind) {
  2059. getXZIntersectionOffsetPoints(p2, p0, u1, q1);
  2060. getXZIntersectionOffsetPoints(p2, p1, u2, q2);
  2061. indices[0] = 2;
  2062. indices[3] = 0;
  2063. indices[4] = 1;
  2064. indices[6] = 0;
  2065. }
  2066. } else if (numBehind === 2) {
  2067. indices[2] = 4;
  2068. indices[4] = 4;
  2069. indices[5] = 3;
  2070. indices[7] = 5;
  2071. indices[8] = 6;
  2072. if (!p0Behind) {
  2073. getXZIntersectionOffsetPoints(p0, p1, u1, q1);
  2074. getXZIntersectionOffsetPoints(p0, p2, u2, q2);
  2075. indices[0] = 1;
  2076. indices[1] = 2;
  2077. indices[3] = 1;
  2078. indices[6] = 0;
  2079. } else if (!p1Behind) {
  2080. getXZIntersectionOffsetPoints(p1, p2, u1, q1);
  2081. getXZIntersectionOffsetPoints(p1, p0, u2, q2);
  2082. indices[0] = 2;
  2083. indices[1] = 0;
  2084. indices[3] = 2;
  2085. indices[6] = 1;
  2086. } else if (!p2Behind) {
  2087. getXZIntersectionOffsetPoints(p2, p0, u1, q1);
  2088. getXZIntersectionOffsetPoints(p2, p1, u2, q2);
  2089. indices[0] = 0;
  2090. indices[1] = 1;
  2091. indices[3] = 0;
  2092. indices[6] = 2;
  2093. }
  2094. }
  2095. var positions = splitTriangleResult.positions;
  2096. positions[0] = p0;
  2097. positions[1] = p1;
  2098. positions[2] = p2;
  2099. positions.length = 3;
  2100. if (numBehind === 1 || numBehind === 2) {
  2101. positions[3] = u1;
  2102. positions[4] = u2;
  2103. positions[5] = q1;
  2104. positions[6] = q2;
  2105. positions.length = 7;
  2106. }
  2107. return splitTriangleResult;
  2108. }
  2109. function updateGeometryAfterSplit(geometry, computeBoundingSphere) {
  2110. var attributes = geometry.attributes;
  2111. if (attributes.position.values.length === 0) {
  2112. return undefined;
  2113. }
  2114. for (var property in attributes) {
  2115. if (
  2116. attributes.hasOwnProperty(property) &&
  2117. when.defined(attributes[property]) &&
  2118. when.defined(attributes[property].values)
  2119. ) {
  2120. var attribute = attributes[property];
  2121. attribute.values = ComponentDatatype.ComponentDatatype.createTypedArray(
  2122. attribute.componentDatatype,
  2123. attribute.values
  2124. );
  2125. }
  2126. }
  2127. var numberOfVertices = GeometryAttribute.Geometry.computeNumberOfVertices(geometry);
  2128. geometry.indices = IndexDatatype.IndexDatatype.createTypedArray(
  2129. numberOfVertices,
  2130. geometry.indices
  2131. );
  2132. if (computeBoundingSphere) {
  2133. geometry.boundingSphere = Transforms.BoundingSphere.fromVertices(
  2134. attributes.position.values
  2135. );
  2136. }
  2137. return geometry;
  2138. }
  2139. function copyGeometryForSplit(geometry) {
  2140. var attributes = geometry.attributes;
  2141. var copiedAttributes = {};
  2142. for (var property in attributes) {
  2143. if (
  2144. attributes.hasOwnProperty(property) &&
  2145. when.defined(attributes[property]) &&
  2146. when.defined(attributes[property].values)
  2147. ) {
  2148. var attribute = attributes[property];
  2149. copiedAttributes[property] = new GeometryAttribute.GeometryAttribute({
  2150. componentDatatype: attribute.componentDatatype,
  2151. componentsPerAttribute: attribute.componentsPerAttribute,
  2152. normalize: attribute.normalize,
  2153. values: [],
  2154. });
  2155. }
  2156. }
  2157. return new GeometryAttribute.Geometry({
  2158. attributes: copiedAttributes,
  2159. indices: [],
  2160. primitiveType: geometry.primitiveType,
  2161. });
  2162. }
  2163. function updateInstanceAfterSplit(instance, westGeometry, eastGeometry) {
  2164. var computeBoundingSphere = when.defined(instance.geometry.boundingSphere);
  2165. westGeometry = updateGeometryAfterSplit(westGeometry, computeBoundingSphere);
  2166. eastGeometry = updateGeometryAfterSplit(eastGeometry, computeBoundingSphere);
  2167. if (when.defined(eastGeometry) && !when.defined(westGeometry)) {
  2168. instance.geometry = eastGeometry;
  2169. } else if (!when.defined(eastGeometry) && when.defined(westGeometry)) {
  2170. instance.geometry = westGeometry;
  2171. } else {
  2172. instance.westHemisphereGeometry = westGeometry;
  2173. instance.eastHemisphereGeometry = eastGeometry;
  2174. instance.geometry = undefined;
  2175. }
  2176. }
  2177. function generateBarycentricInterpolateFunction(
  2178. CartesianType,
  2179. numberOfComponents
  2180. ) {
  2181. var v0Scratch = new CartesianType();
  2182. var v1Scratch = new CartesianType();
  2183. var v2Scratch = new CartesianType();
  2184. return function (
  2185. i0,
  2186. i1,
  2187. i2,
  2188. coords,
  2189. sourceValues,
  2190. currentValues,
  2191. insertedIndex,
  2192. normalize
  2193. ) {
  2194. var v0 = CartesianType.fromArray(
  2195. sourceValues,
  2196. i0 * numberOfComponents,
  2197. v0Scratch
  2198. );
  2199. var v1 = CartesianType.fromArray(
  2200. sourceValues,
  2201. i1 * numberOfComponents,
  2202. v1Scratch
  2203. );
  2204. var v2 = CartesianType.fromArray(
  2205. sourceValues,
  2206. i2 * numberOfComponents,
  2207. v2Scratch
  2208. );
  2209. CartesianType.multiplyByScalar(v0, coords.x, v0);
  2210. CartesianType.multiplyByScalar(v1, coords.y, v1);
  2211. CartesianType.multiplyByScalar(v2, coords.z, v2);
  2212. var value = CartesianType.add(v0, v1, v0);
  2213. CartesianType.add(value, v2, value);
  2214. if (normalize) {
  2215. CartesianType.normalize(value, value);
  2216. }
  2217. CartesianType.pack(
  2218. value,
  2219. currentValues,
  2220. insertedIndex * numberOfComponents
  2221. );
  2222. };
  2223. }
  2224. var interpolateAndPackCartesian4 = generateBarycentricInterpolateFunction(
  2225. Transforms.Cartesian4,
  2226. 4
  2227. );
  2228. var interpolateAndPackCartesian3 = generateBarycentricInterpolateFunction(
  2229. Cartesian2.Cartesian3,
  2230. 3
  2231. );
  2232. var interpolateAndPackCartesian2 = generateBarycentricInterpolateFunction(
  2233. Cartesian2.Cartesian2,
  2234. 2
  2235. );
  2236. var interpolateAndPackBoolean = function (
  2237. i0,
  2238. i1,
  2239. i2,
  2240. coords,
  2241. sourceValues,
  2242. currentValues,
  2243. insertedIndex
  2244. ) {
  2245. var v1 = sourceValues[i0] * coords.x;
  2246. var v2 = sourceValues[i1] * coords.y;
  2247. var v3 = sourceValues[i2] * coords.z;
  2248. currentValues[insertedIndex] = v1 + v2 + v3 > _Math.CesiumMath.EPSILON6 ? 1 : 0;
  2249. };
  2250. var p0Scratch = new Cartesian2.Cartesian3();
  2251. var p1Scratch = new Cartesian2.Cartesian3();
  2252. var p2Scratch = new Cartesian2.Cartesian3();
  2253. var barycentricScratch = new Cartesian2.Cartesian3();
  2254. function computeTriangleAttributes(
  2255. i0,
  2256. i1,
  2257. i2,
  2258. point,
  2259. positions,
  2260. normals,
  2261. tangents,
  2262. bitangents,
  2263. texCoords,
  2264. extrudeDirections,
  2265. applyOffset,
  2266. currentAttributes,
  2267. customAttributeNames,
  2268. customAttributesLength,
  2269. allAttributes,
  2270. insertedIndex
  2271. ) {
  2272. if (
  2273. !when.defined(normals) &&
  2274. !when.defined(tangents) &&
  2275. !when.defined(bitangents) &&
  2276. !when.defined(texCoords) &&
  2277. !when.defined(extrudeDirections) &&
  2278. customAttributesLength === 0
  2279. ) {
  2280. return;
  2281. }
  2282. var p0 = Cartesian2.Cartesian3.fromArray(positions, i0 * 3, p0Scratch);
  2283. var p1 = Cartesian2.Cartesian3.fromArray(positions, i1 * 3, p1Scratch);
  2284. var p2 = Cartesian2.Cartesian3.fromArray(positions, i2 * 3, p2Scratch);
  2285. var coords = barycentricCoordinates(point, p0, p1, p2, barycentricScratch);
  2286. if (when.defined(normals)) {
  2287. interpolateAndPackCartesian3(
  2288. i0,
  2289. i1,
  2290. i2,
  2291. coords,
  2292. normals,
  2293. currentAttributes.normal.values,
  2294. insertedIndex,
  2295. true
  2296. );
  2297. }
  2298. if (when.defined(extrudeDirections)) {
  2299. var d0 = Cartesian2.Cartesian3.fromArray(extrudeDirections, i0 * 3, p0Scratch);
  2300. var d1 = Cartesian2.Cartesian3.fromArray(extrudeDirections, i1 * 3, p1Scratch);
  2301. var d2 = Cartesian2.Cartesian3.fromArray(extrudeDirections, i2 * 3, p2Scratch);
  2302. Cartesian2.Cartesian3.multiplyByScalar(d0, coords.x, d0);
  2303. Cartesian2.Cartesian3.multiplyByScalar(d1, coords.y, d1);
  2304. Cartesian2.Cartesian3.multiplyByScalar(d2, coords.z, d2);
  2305. var direction;
  2306. if (
  2307. !Cartesian2.Cartesian3.equals(d0, Cartesian2.Cartesian3.ZERO) ||
  2308. !Cartesian2.Cartesian3.equals(d1, Cartesian2.Cartesian3.ZERO) ||
  2309. !Cartesian2.Cartesian3.equals(d2, Cartesian2.Cartesian3.ZERO)
  2310. ) {
  2311. direction = Cartesian2.Cartesian3.add(d0, d1, d0);
  2312. Cartesian2.Cartesian3.add(direction, d2, direction);
  2313. Cartesian2.Cartesian3.normalize(direction, direction);
  2314. } else {
  2315. direction = p0Scratch;
  2316. direction.x = 0;
  2317. direction.y = 0;
  2318. direction.z = 0;
  2319. }
  2320. Cartesian2.Cartesian3.pack(
  2321. direction,
  2322. currentAttributes.extrudeDirection.values,
  2323. insertedIndex * 3
  2324. );
  2325. }
  2326. if (when.defined(applyOffset)) {
  2327. interpolateAndPackBoolean(
  2328. i0,
  2329. i1,
  2330. i2,
  2331. coords,
  2332. applyOffset,
  2333. currentAttributes.applyOffset.values,
  2334. insertedIndex
  2335. );
  2336. }
  2337. if (when.defined(tangents)) {
  2338. interpolateAndPackCartesian3(
  2339. i0,
  2340. i1,
  2341. i2,
  2342. coords,
  2343. tangents,
  2344. currentAttributes.tangent.values,
  2345. insertedIndex,
  2346. true
  2347. );
  2348. }
  2349. if (when.defined(bitangents)) {
  2350. interpolateAndPackCartesian3(
  2351. i0,
  2352. i1,
  2353. i2,
  2354. coords,
  2355. bitangents,
  2356. currentAttributes.bitangent.values,
  2357. insertedIndex,
  2358. true
  2359. );
  2360. }
  2361. if (when.defined(texCoords)) {
  2362. interpolateAndPackCartesian2(
  2363. i0,
  2364. i1,
  2365. i2,
  2366. coords,
  2367. texCoords,
  2368. currentAttributes.st.values,
  2369. insertedIndex
  2370. );
  2371. }
  2372. if (customAttributesLength > 0) {
  2373. for (var i = 0; i < customAttributesLength; i++) {
  2374. var attributeName = customAttributeNames[i];
  2375. genericInterpolate(
  2376. i0,
  2377. i1,
  2378. i2,
  2379. coords,
  2380. insertedIndex,
  2381. allAttributes[attributeName],
  2382. currentAttributes[attributeName]
  2383. );
  2384. }
  2385. }
  2386. }
  2387. function genericInterpolate(
  2388. i0,
  2389. i1,
  2390. i2,
  2391. coords,
  2392. insertedIndex,
  2393. sourceAttribute,
  2394. currentAttribute
  2395. ) {
  2396. var componentsPerAttribute = sourceAttribute.componentsPerAttribute;
  2397. var sourceValues = sourceAttribute.values;
  2398. var currentValues = currentAttribute.values;
  2399. switch (componentsPerAttribute) {
  2400. case 4:
  2401. interpolateAndPackCartesian4(
  2402. i0,
  2403. i1,
  2404. i2,
  2405. coords,
  2406. sourceValues,
  2407. currentValues,
  2408. insertedIndex,
  2409. false
  2410. );
  2411. break;
  2412. case 3:
  2413. interpolateAndPackCartesian3(
  2414. i0,
  2415. i1,
  2416. i2,
  2417. coords,
  2418. sourceValues,
  2419. currentValues,
  2420. insertedIndex,
  2421. false
  2422. );
  2423. break;
  2424. case 2:
  2425. interpolateAndPackCartesian2(
  2426. i0,
  2427. i1,
  2428. i2,
  2429. coords,
  2430. sourceValues,
  2431. currentValues,
  2432. insertedIndex,
  2433. false
  2434. );
  2435. break;
  2436. default:
  2437. currentValues[insertedIndex] =
  2438. sourceValues[i0] * coords.x +
  2439. sourceValues[i1] * coords.y +
  2440. sourceValues[i2] * coords.z;
  2441. }
  2442. }
  2443. function insertSplitPoint(
  2444. currentAttributes,
  2445. currentIndices,
  2446. currentIndexMap,
  2447. indices,
  2448. currentIndex,
  2449. point
  2450. ) {
  2451. var insertIndex = currentAttributes.position.values.length / 3;
  2452. if (currentIndex !== -1) {
  2453. var prevIndex = indices[currentIndex];
  2454. var newIndex = currentIndexMap[prevIndex];
  2455. if (newIndex === -1) {
  2456. currentIndexMap[prevIndex] = insertIndex;
  2457. currentAttributes.position.values.push(point.x, point.y, point.z);
  2458. currentIndices.push(insertIndex);
  2459. return insertIndex;
  2460. }
  2461. currentIndices.push(newIndex);
  2462. return newIndex;
  2463. }
  2464. currentAttributes.position.values.push(point.x, point.y, point.z);
  2465. currentIndices.push(insertIndex);
  2466. return insertIndex;
  2467. }
  2468. var NAMED_ATTRIBUTES = {
  2469. position: true,
  2470. normal: true,
  2471. bitangent: true,
  2472. tangent: true,
  2473. st: true,
  2474. extrudeDirection: true,
  2475. applyOffset: true,
  2476. };
  2477. function splitLongitudeTriangles(instance) {
  2478. var geometry = instance.geometry;
  2479. var attributes = geometry.attributes;
  2480. var positions = attributes.position.values;
  2481. var normals = when.defined(attributes.normal)
  2482. ? attributes.normal.values
  2483. : undefined;
  2484. var bitangents = when.defined(attributes.bitangent)
  2485. ? attributes.bitangent.values
  2486. : undefined;
  2487. var tangents = when.defined(attributes.tangent)
  2488. ? attributes.tangent.values
  2489. : undefined;
  2490. var texCoords = when.defined(attributes.st) ? attributes.st.values : undefined;
  2491. var extrudeDirections = when.defined(attributes.extrudeDirection)
  2492. ? attributes.extrudeDirection.values
  2493. : undefined;
  2494. var applyOffset = when.defined(attributes.applyOffset)
  2495. ? attributes.applyOffset.values
  2496. : undefined;
  2497. var indices = geometry.indices;
  2498. var customAttributeNames = [];
  2499. for (var attributeName in attributes) {
  2500. if (
  2501. attributes.hasOwnProperty(attributeName) &&
  2502. !NAMED_ATTRIBUTES[attributeName] &&
  2503. when.defined(attributes[attributeName])
  2504. ) {
  2505. customAttributeNames.push(attributeName);
  2506. }
  2507. }
  2508. var customAttributesLength = customAttributeNames.length;
  2509. var eastGeometry = copyGeometryForSplit(geometry);
  2510. var westGeometry = copyGeometryForSplit(geometry);
  2511. var currentAttributes;
  2512. var currentIndices;
  2513. var currentIndexMap;
  2514. var insertedIndex;
  2515. var i;
  2516. var westGeometryIndexMap = [];
  2517. westGeometryIndexMap.length = positions.length / 3;
  2518. var eastGeometryIndexMap = [];
  2519. eastGeometryIndexMap.length = positions.length / 3;
  2520. for (i = 0; i < westGeometryIndexMap.length; ++i) {
  2521. westGeometryIndexMap[i] = -1;
  2522. eastGeometryIndexMap[i] = -1;
  2523. }
  2524. var len = indices.length;
  2525. for (i = 0; i < len; i += 3) {
  2526. var i0 = indices[i];
  2527. var i1 = indices[i + 1];
  2528. var i2 = indices[i + 2];
  2529. var p0 = Cartesian2.Cartesian3.fromArray(positions, i0 * 3);
  2530. var p1 = Cartesian2.Cartesian3.fromArray(positions, i1 * 3);
  2531. var p2 = Cartesian2.Cartesian3.fromArray(positions, i2 * 3);
  2532. var result = splitTriangle(p0, p1, p2);
  2533. if (when.defined(result) && result.positions.length > 3) {
  2534. var resultPositions = result.positions;
  2535. var resultIndices = result.indices;
  2536. var resultLength = resultIndices.length;
  2537. for (var j = 0; j < resultLength; ++j) {
  2538. var resultIndex = resultIndices[j];
  2539. var point = resultPositions[resultIndex];
  2540. if (point.y < 0.0) {
  2541. currentAttributes = westGeometry.attributes;
  2542. currentIndices = westGeometry.indices;
  2543. currentIndexMap = westGeometryIndexMap;
  2544. } else {
  2545. currentAttributes = eastGeometry.attributes;
  2546. currentIndices = eastGeometry.indices;
  2547. currentIndexMap = eastGeometryIndexMap;
  2548. }
  2549. insertedIndex = insertSplitPoint(
  2550. currentAttributes,
  2551. currentIndices,
  2552. currentIndexMap,
  2553. indices,
  2554. resultIndex < 3 ? i + resultIndex : -1,
  2555. point
  2556. );
  2557. computeTriangleAttributes(
  2558. i0,
  2559. i1,
  2560. i2,
  2561. point,
  2562. positions,
  2563. normals,
  2564. tangents,
  2565. bitangents,
  2566. texCoords,
  2567. extrudeDirections,
  2568. applyOffset,
  2569. currentAttributes,
  2570. customAttributeNames,
  2571. customAttributesLength,
  2572. attributes,
  2573. insertedIndex
  2574. );
  2575. }
  2576. } else {
  2577. if (when.defined(result)) {
  2578. p0 = result.positions[0];
  2579. p1 = result.positions[1];
  2580. p2 = result.positions[2];
  2581. }
  2582. if (p0.y < 0.0) {
  2583. currentAttributes = westGeometry.attributes;
  2584. currentIndices = westGeometry.indices;
  2585. currentIndexMap = westGeometryIndexMap;
  2586. } else {
  2587. currentAttributes = eastGeometry.attributes;
  2588. currentIndices = eastGeometry.indices;
  2589. currentIndexMap = eastGeometryIndexMap;
  2590. }
  2591. insertedIndex = insertSplitPoint(
  2592. currentAttributes,
  2593. currentIndices,
  2594. currentIndexMap,
  2595. indices,
  2596. i,
  2597. p0
  2598. );
  2599. computeTriangleAttributes(
  2600. i0,
  2601. i1,
  2602. i2,
  2603. p0,
  2604. positions,
  2605. normals,
  2606. tangents,
  2607. bitangents,
  2608. texCoords,
  2609. extrudeDirections,
  2610. applyOffset,
  2611. currentAttributes,
  2612. customAttributeNames,
  2613. customAttributesLength,
  2614. attributes,
  2615. insertedIndex
  2616. );
  2617. insertedIndex = insertSplitPoint(
  2618. currentAttributes,
  2619. currentIndices,
  2620. currentIndexMap,
  2621. indices,
  2622. i + 1,
  2623. p1
  2624. );
  2625. computeTriangleAttributes(
  2626. i0,
  2627. i1,
  2628. i2,
  2629. p1,
  2630. positions,
  2631. normals,
  2632. tangents,
  2633. bitangents,
  2634. texCoords,
  2635. extrudeDirections,
  2636. applyOffset,
  2637. currentAttributes,
  2638. customAttributeNames,
  2639. customAttributesLength,
  2640. attributes,
  2641. insertedIndex
  2642. );
  2643. insertedIndex = insertSplitPoint(
  2644. currentAttributes,
  2645. currentIndices,
  2646. currentIndexMap,
  2647. indices,
  2648. i + 2,
  2649. p2
  2650. );
  2651. computeTriangleAttributes(
  2652. i0,
  2653. i1,
  2654. i2,
  2655. p2,
  2656. positions,
  2657. normals,
  2658. tangents,
  2659. bitangents,
  2660. texCoords,
  2661. extrudeDirections,
  2662. applyOffset,
  2663. currentAttributes,
  2664. customAttributeNames,
  2665. customAttributesLength,
  2666. attributes,
  2667. insertedIndex
  2668. );
  2669. }
  2670. }
  2671. updateInstanceAfterSplit(instance, westGeometry, eastGeometry);
  2672. }
  2673. var xzPlane = Plane.Plane.fromPointNormal(Cartesian2.Cartesian3.ZERO, Cartesian2.Cartesian3.UNIT_Y);
  2674. var offsetScratch = new Cartesian2.Cartesian3();
  2675. var offsetPointScratch = new Cartesian2.Cartesian3();
  2676. function computeLineAttributes(
  2677. i0,
  2678. i1,
  2679. point,
  2680. positions,
  2681. insertIndex,
  2682. currentAttributes,
  2683. applyOffset
  2684. ) {
  2685. if (!when.defined(applyOffset)) {
  2686. return;
  2687. }
  2688. var p0 = Cartesian2.Cartesian3.fromArray(positions, i0 * 3, p0Scratch);
  2689. if (Cartesian2.Cartesian3.equalsEpsilon(p0, point, _Math.CesiumMath.EPSILON10)) {
  2690. currentAttributes.applyOffset.values[insertIndex] = applyOffset[i0];
  2691. } else {
  2692. currentAttributes.applyOffset.values[insertIndex] = applyOffset[i1];
  2693. }
  2694. }
  2695. function splitLongitudeLines(instance) {
  2696. var geometry = instance.geometry;
  2697. var attributes = geometry.attributes;
  2698. var positions = attributes.position.values;
  2699. var applyOffset = when.defined(attributes.applyOffset)
  2700. ? attributes.applyOffset.values
  2701. : undefined;
  2702. var indices = geometry.indices;
  2703. var eastGeometry = copyGeometryForSplit(geometry);
  2704. var westGeometry = copyGeometryForSplit(geometry);
  2705. var i;
  2706. var length = indices.length;
  2707. var westGeometryIndexMap = [];
  2708. westGeometryIndexMap.length = positions.length / 3;
  2709. var eastGeometryIndexMap = [];
  2710. eastGeometryIndexMap.length = positions.length / 3;
  2711. for (i = 0; i < westGeometryIndexMap.length; ++i) {
  2712. westGeometryIndexMap[i] = -1;
  2713. eastGeometryIndexMap[i] = -1;
  2714. }
  2715. for (i = 0; i < length; i += 2) {
  2716. var i0 = indices[i];
  2717. var i1 = indices[i + 1];
  2718. var p0 = Cartesian2.Cartesian3.fromArray(positions, i0 * 3, p0Scratch);
  2719. var p1 = Cartesian2.Cartesian3.fromArray(positions, i1 * 3, p1Scratch);
  2720. var insertIndex;
  2721. if (Math.abs(p0.y) < _Math.CesiumMath.EPSILON6) {
  2722. if (p0.y < 0.0) {
  2723. p0.y = -_Math.CesiumMath.EPSILON6;
  2724. } else {
  2725. p0.y = _Math.CesiumMath.EPSILON6;
  2726. }
  2727. }
  2728. if (Math.abs(p1.y) < _Math.CesiumMath.EPSILON6) {
  2729. if (p1.y < 0.0) {
  2730. p1.y = -_Math.CesiumMath.EPSILON6;
  2731. } else {
  2732. p1.y = _Math.CesiumMath.EPSILON6;
  2733. }
  2734. }
  2735. var p0Attributes = eastGeometry.attributes;
  2736. var p0Indices = eastGeometry.indices;
  2737. var p0IndexMap = eastGeometryIndexMap;
  2738. var p1Attributes = westGeometry.attributes;
  2739. var p1Indices = westGeometry.indices;
  2740. var p1IndexMap = westGeometryIndexMap;
  2741. var intersection = IntersectionTests.IntersectionTests.lineSegmentPlane(
  2742. p0,
  2743. p1,
  2744. xzPlane,
  2745. p2Scratch
  2746. );
  2747. if (when.defined(intersection)) {
  2748. // move point on the xz-plane slightly away from the plane
  2749. var offset = Cartesian2.Cartesian3.multiplyByScalar(
  2750. Cartesian2.Cartesian3.UNIT_Y,
  2751. 5.0 * _Math.CesiumMath.EPSILON9,
  2752. offsetScratch
  2753. );
  2754. if (p0.y < 0.0) {
  2755. Cartesian2.Cartesian3.negate(offset, offset);
  2756. p0Attributes = westGeometry.attributes;
  2757. p0Indices = westGeometry.indices;
  2758. p0IndexMap = westGeometryIndexMap;
  2759. p1Attributes = eastGeometry.attributes;
  2760. p1Indices = eastGeometry.indices;
  2761. p1IndexMap = eastGeometryIndexMap;
  2762. }
  2763. var offsetPoint = Cartesian2.Cartesian3.add(
  2764. intersection,
  2765. offset,
  2766. offsetPointScratch
  2767. );
  2768. insertIndex = insertSplitPoint(
  2769. p0Attributes,
  2770. p0Indices,
  2771. p0IndexMap,
  2772. indices,
  2773. i,
  2774. p0
  2775. );
  2776. computeLineAttributes(
  2777. i0,
  2778. i1,
  2779. p0,
  2780. positions,
  2781. insertIndex,
  2782. p0Attributes,
  2783. applyOffset
  2784. );
  2785. insertIndex = insertSplitPoint(
  2786. p0Attributes,
  2787. p0Indices,
  2788. p0IndexMap,
  2789. indices,
  2790. -1,
  2791. offsetPoint
  2792. );
  2793. computeLineAttributes(
  2794. i0,
  2795. i1,
  2796. offsetPoint,
  2797. positions,
  2798. insertIndex,
  2799. p0Attributes,
  2800. applyOffset
  2801. );
  2802. Cartesian2.Cartesian3.negate(offset, offset);
  2803. Cartesian2.Cartesian3.add(intersection, offset, offsetPoint);
  2804. insertIndex = insertSplitPoint(
  2805. p1Attributes,
  2806. p1Indices,
  2807. p1IndexMap,
  2808. indices,
  2809. -1,
  2810. offsetPoint
  2811. );
  2812. computeLineAttributes(
  2813. i0,
  2814. i1,
  2815. offsetPoint,
  2816. positions,
  2817. insertIndex,
  2818. p1Attributes,
  2819. applyOffset
  2820. );
  2821. insertIndex = insertSplitPoint(
  2822. p1Attributes,
  2823. p1Indices,
  2824. p1IndexMap,
  2825. indices,
  2826. i + 1,
  2827. p1
  2828. );
  2829. computeLineAttributes(
  2830. i0,
  2831. i1,
  2832. p1,
  2833. positions,
  2834. insertIndex,
  2835. p1Attributes,
  2836. applyOffset
  2837. );
  2838. } else {
  2839. var currentAttributes;
  2840. var currentIndices;
  2841. var currentIndexMap;
  2842. if (p0.y < 0.0) {
  2843. currentAttributes = westGeometry.attributes;
  2844. currentIndices = westGeometry.indices;
  2845. currentIndexMap = westGeometryIndexMap;
  2846. } else {
  2847. currentAttributes = eastGeometry.attributes;
  2848. currentIndices = eastGeometry.indices;
  2849. currentIndexMap = eastGeometryIndexMap;
  2850. }
  2851. insertIndex = insertSplitPoint(
  2852. currentAttributes,
  2853. currentIndices,
  2854. currentIndexMap,
  2855. indices,
  2856. i,
  2857. p0
  2858. );
  2859. computeLineAttributes(
  2860. i0,
  2861. i1,
  2862. p0,
  2863. positions,
  2864. insertIndex,
  2865. currentAttributes,
  2866. applyOffset
  2867. );
  2868. insertIndex = insertSplitPoint(
  2869. currentAttributes,
  2870. currentIndices,
  2871. currentIndexMap,
  2872. indices,
  2873. i + 1,
  2874. p1
  2875. );
  2876. computeLineAttributes(
  2877. i0,
  2878. i1,
  2879. p1,
  2880. positions,
  2881. insertIndex,
  2882. currentAttributes,
  2883. applyOffset
  2884. );
  2885. }
  2886. }
  2887. updateInstanceAfterSplit(instance, westGeometry, eastGeometry);
  2888. }
  2889. var cartesian2Scratch0 = new Cartesian2.Cartesian2();
  2890. var cartesian2Scratch1 = new Cartesian2.Cartesian2();
  2891. var cartesian3Scratch0 = new Cartesian2.Cartesian3();
  2892. var cartesian3Scratch2 = new Cartesian2.Cartesian3();
  2893. var cartesian3Scratch3 = new Cartesian2.Cartesian3();
  2894. var cartesian3Scratch4 = new Cartesian2.Cartesian3();
  2895. var cartesian3Scratch5 = new Cartesian2.Cartesian3();
  2896. var cartesian3Scratch6 = new Cartesian2.Cartesian3();
  2897. var cartesian4Scratch0 = new Transforms.Cartesian4();
  2898. function updateAdjacencyAfterSplit(geometry) {
  2899. var attributes = geometry.attributes;
  2900. var positions = attributes.position.values;
  2901. var prevPositions = attributes.prevPosition.values;
  2902. var nextPositions = attributes.nextPosition.values;
  2903. var length = positions.length;
  2904. for (var j = 0; j < length; j += 3) {
  2905. var position = Cartesian2.Cartesian3.unpack(positions, j, cartesian3Scratch0);
  2906. if (position.x > 0.0) {
  2907. continue;
  2908. }
  2909. var prevPosition = Cartesian2.Cartesian3.unpack(prevPositions, j, cartesian3Scratch2);
  2910. if (
  2911. (position.y < 0.0 && prevPosition.y > 0.0) ||
  2912. (position.y > 0.0 && prevPosition.y < 0.0)
  2913. ) {
  2914. if (j - 3 > 0) {
  2915. prevPositions[j] = positions[j - 3];
  2916. prevPositions[j + 1] = positions[j - 2];
  2917. prevPositions[j + 2] = positions[j - 1];
  2918. } else {
  2919. Cartesian2.Cartesian3.pack(position, prevPositions, j);
  2920. }
  2921. }
  2922. var nextPosition = Cartesian2.Cartesian3.unpack(nextPositions, j, cartesian3Scratch3);
  2923. if (
  2924. (position.y < 0.0 && nextPosition.y > 0.0) ||
  2925. (position.y > 0.0 && nextPosition.y < 0.0)
  2926. ) {
  2927. if (j + 3 < length) {
  2928. nextPositions[j] = positions[j + 3];
  2929. nextPositions[j + 1] = positions[j + 4];
  2930. nextPositions[j + 2] = positions[j + 5];
  2931. } else {
  2932. Cartesian2.Cartesian3.pack(position, nextPositions, j);
  2933. }
  2934. }
  2935. }
  2936. }
  2937. var offsetScalar = 5.0 * _Math.CesiumMath.EPSILON9;
  2938. var coplanarOffset = _Math.CesiumMath.EPSILON6;
  2939. function splitLongitudePolyline(instance) {
  2940. var geometry = instance.geometry;
  2941. var attributes = geometry.attributes;
  2942. var positions = attributes.position.values;
  2943. var prevPositions = attributes.prevPosition.values;
  2944. var nextPositions = attributes.nextPosition.values;
  2945. var expandAndWidths = attributes.expandAndWidth.values;
  2946. var texCoords = when.defined(attributes.st) ? attributes.st.values : undefined;
  2947. var colors = when.defined(attributes.color) ? attributes.color.values : undefined;
  2948. var eastGeometry = copyGeometryForSplit(geometry);
  2949. var westGeometry = copyGeometryForSplit(geometry);
  2950. var i;
  2951. var j;
  2952. var index;
  2953. var intersectionFound = false;
  2954. var length = positions.length / 3;
  2955. for (i = 0; i < length; i += 4) {
  2956. var i0 = i;
  2957. var i2 = i + 2;
  2958. var p0 = Cartesian2.Cartesian3.fromArray(positions, i0 * 3, cartesian3Scratch0);
  2959. var p2 = Cartesian2.Cartesian3.fromArray(positions, i2 * 3, cartesian3Scratch2);
  2960. // Offset points that are close to the 180 longitude and change the previous/next point
  2961. // to be the same offset point so it can be projected to 2D. There is special handling in the
  2962. // shader for when position == prevPosition || position == nextPosition.
  2963. if (Math.abs(p0.y) < coplanarOffset) {
  2964. p0.y = coplanarOffset * (p2.y < 0.0 ? -1.0 : 1.0);
  2965. positions[i * 3 + 1] = p0.y;
  2966. positions[(i + 1) * 3 + 1] = p0.y;
  2967. for (j = i0 * 3; j < i0 * 3 + 4 * 3; j += 3) {
  2968. prevPositions[j] = positions[i * 3];
  2969. prevPositions[j + 1] = positions[i * 3 + 1];
  2970. prevPositions[j + 2] = positions[i * 3 + 2];
  2971. }
  2972. }
  2973. // Do the same but for when the line crosses 180 longitude in the opposite direction.
  2974. if (Math.abs(p2.y) < coplanarOffset) {
  2975. p2.y = coplanarOffset * (p0.y < 0.0 ? -1.0 : 1.0);
  2976. positions[(i + 2) * 3 + 1] = p2.y;
  2977. positions[(i + 3) * 3 + 1] = p2.y;
  2978. for (j = i0 * 3; j < i0 * 3 + 4 * 3; j += 3) {
  2979. nextPositions[j] = positions[(i + 2) * 3];
  2980. nextPositions[j + 1] = positions[(i + 2) * 3 + 1];
  2981. nextPositions[j + 2] = positions[(i + 2) * 3 + 2];
  2982. }
  2983. }
  2984. var p0Attributes = eastGeometry.attributes;
  2985. var p0Indices = eastGeometry.indices;
  2986. var p2Attributes = westGeometry.attributes;
  2987. var p2Indices = westGeometry.indices;
  2988. var intersection = IntersectionTests.IntersectionTests.lineSegmentPlane(
  2989. p0,
  2990. p2,
  2991. xzPlane,
  2992. cartesian3Scratch4
  2993. );
  2994. if (when.defined(intersection)) {
  2995. intersectionFound = true;
  2996. // move point on the xz-plane slightly away from the plane
  2997. var offset = Cartesian2.Cartesian3.multiplyByScalar(
  2998. Cartesian2.Cartesian3.UNIT_Y,
  2999. offsetScalar,
  3000. cartesian3Scratch5
  3001. );
  3002. if (p0.y < 0.0) {
  3003. Cartesian2.Cartesian3.negate(offset, offset);
  3004. p0Attributes = westGeometry.attributes;
  3005. p0Indices = westGeometry.indices;
  3006. p2Attributes = eastGeometry.attributes;
  3007. p2Indices = eastGeometry.indices;
  3008. }
  3009. var offsetPoint = Cartesian2.Cartesian3.add(
  3010. intersection,
  3011. offset,
  3012. cartesian3Scratch6
  3013. );
  3014. p0Attributes.position.values.push(p0.x, p0.y, p0.z, p0.x, p0.y, p0.z);
  3015. p0Attributes.position.values.push(
  3016. offsetPoint.x,
  3017. offsetPoint.y,
  3018. offsetPoint.z
  3019. );
  3020. p0Attributes.position.values.push(
  3021. offsetPoint.x,
  3022. offsetPoint.y,
  3023. offsetPoint.z
  3024. );
  3025. p0Attributes.prevPosition.values.push(
  3026. prevPositions[i0 * 3],
  3027. prevPositions[i0 * 3 + 1],
  3028. prevPositions[i0 * 3 + 2]
  3029. );
  3030. p0Attributes.prevPosition.values.push(
  3031. prevPositions[i0 * 3 + 3],
  3032. prevPositions[i0 * 3 + 4],
  3033. prevPositions[i0 * 3 + 5]
  3034. );
  3035. p0Attributes.prevPosition.values.push(p0.x, p0.y, p0.z, p0.x, p0.y, p0.z);
  3036. p0Attributes.nextPosition.values.push(
  3037. offsetPoint.x,
  3038. offsetPoint.y,
  3039. offsetPoint.z
  3040. );
  3041. p0Attributes.nextPosition.values.push(
  3042. offsetPoint.x,
  3043. offsetPoint.y,
  3044. offsetPoint.z
  3045. );
  3046. p0Attributes.nextPosition.values.push(
  3047. offsetPoint.x,
  3048. offsetPoint.y,
  3049. offsetPoint.z
  3050. );
  3051. p0Attributes.nextPosition.values.push(
  3052. offsetPoint.x,
  3053. offsetPoint.y,
  3054. offsetPoint.z
  3055. );
  3056. Cartesian2.Cartesian3.negate(offset, offset);
  3057. Cartesian2.Cartesian3.add(intersection, offset, offsetPoint);
  3058. p2Attributes.position.values.push(
  3059. offsetPoint.x,
  3060. offsetPoint.y,
  3061. offsetPoint.z
  3062. );
  3063. p2Attributes.position.values.push(
  3064. offsetPoint.x,
  3065. offsetPoint.y,
  3066. offsetPoint.z
  3067. );
  3068. p2Attributes.position.values.push(p2.x, p2.y, p2.z, p2.x, p2.y, p2.z);
  3069. p2Attributes.prevPosition.values.push(
  3070. offsetPoint.x,
  3071. offsetPoint.y,
  3072. offsetPoint.z
  3073. );
  3074. p2Attributes.prevPosition.values.push(
  3075. offsetPoint.x,
  3076. offsetPoint.y,
  3077. offsetPoint.z
  3078. );
  3079. p2Attributes.prevPosition.values.push(
  3080. offsetPoint.x,
  3081. offsetPoint.y,
  3082. offsetPoint.z
  3083. );
  3084. p2Attributes.prevPosition.values.push(
  3085. offsetPoint.x,
  3086. offsetPoint.y,
  3087. offsetPoint.z
  3088. );
  3089. p2Attributes.nextPosition.values.push(p2.x, p2.y, p2.z, p2.x, p2.y, p2.z);
  3090. p2Attributes.nextPosition.values.push(
  3091. nextPositions[i2 * 3],
  3092. nextPositions[i2 * 3 + 1],
  3093. nextPositions[i2 * 3 + 2]
  3094. );
  3095. p2Attributes.nextPosition.values.push(
  3096. nextPositions[i2 * 3 + 3],
  3097. nextPositions[i2 * 3 + 4],
  3098. nextPositions[i2 * 3 + 5]
  3099. );
  3100. var ew0 = Cartesian2.Cartesian2.fromArray(
  3101. expandAndWidths,
  3102. i0 * 2,
  3103. cartesian2Scratch0
  3104. );
  3105. var width = Math.abs(ew0.y);
  3106. p0Attributes.expandAndWidth.values.push(-1, width, 1, width);
  3107. p0Attributes.expandAndWidth.values.push(-1, -width, 1, -width);
  3108. p2Attributes.expandAndWidth.values.push(-1, width, 1, width);
  3109. p2Attributes.expandAndWidth.values.push(-1, -width, 1, -width);
  3110. var t = Cartesian2.Cartesian3.magnitudeSquared(
  3111. Cartesian2.Cartesian3.subtract(intersection, p0, cartesian3Scratch3)
  3112. );
  3113. t /= Cartesian2.Cartesian3.magnitudeSquared(
  3114. Cartesian2.Cartesian3.subtract(p2, p0, cartesian3Scratch3)
  3115. );
  3116. if (when.defined(colors)) {
  3117. var c0 = Transforms.Cartesian4.fromArray(colors, i0 * 4, cartesian4Scratch0);
  3118. var c2 = Transforms.Cartesian4.fromArray(colors, i2 * 4, cartesian4Scratch0);
  3119. var r = _Math.CesiumMath.lerp(c0.x, c2.x, t);
  3120. var g = _Math.CesiumMath.lerp(c0.y, c2.y, t);
  3121. var b = _Math.CesiumMath.lerp(c0.z, c2.z, t);
  3122. var a = _Math.CesiumMath.lerp(c0.w, c2.w, t);
  3123. for (j = i0 * 4; j < i0 * 4 + 2 * 4; ++j) {
  3124. p0Attributes.color.values.push(colors[j]);
  3125. }
  3126. p0Attributes.color.values.push(r, g, b, a);
  3127. p0Attributes.color.values.push(r, g, b, a);
  3128. p2Attributes.color.values.push(r, g, b, a);
  3129. p2Attributes.color.values.push(r, g, b, a);
  3130. for (j = i2 * 4; j < i2 * 4 + 2 * 4; ++j) {
  3131. p2Attributes.color.values.push(colors[j]);
  3132. }
  3133. }
  3134. if (when.defined(texCoords)) {
  3135. var s0 = Cartesian2.Cartesian2.fromArray(texCoords, i0 * 2, cartesian2Scratch0);
  3136. var s3 = Cartesian2.Cartesian2.fromArray(
  3137. texCoords,
  3138. (i + 3) * 2,
  3139. cartesian2Scratch1
  3140. );
  3141. var sx = _Math.CesiumMath.lerp(s0.x, s3.x, t);
  3142. for (j = i0 * 2; j < i0 * 2 + 2 * 2; ++j) {
  3143. p0Attributes.st.values.push(texCoords[j]);
  3144. }
  3145. p0Attributes.st.values.push(sx, s0.y);
  3146. p0Attributes.st.values.push(sx, s3.y);
  3147. p2Attributes.st.values.push(sx, s0.y);
  3148. p2Attributes.st.values.push(sx, s3.y);
  3149. for (j = i2 * 2; j < i2 * 2 + 2 * 2; ++j) {
  3150. p2Attributes.st.values.push(texCoords[j]);
  3151. }
  3152. }
  3153. index = p0Attributes.position.values.length / 3 - 4;
  3154. p0Indices.push(index, index + 2, index + 1);
  3155. p0Indices.push(index + 1, index + 2, index + 3);
  3156. index = p2Attributes.position.values.length / 3 - 4;
  3157. p2Indices.push(index, index + 2, index + 1);
  3158. p2Indices.push(index + 1, index + 2, index + 3);
  3159. } else {
  3160. var currentAttributes;
  3161. var currentIndices;
  3162. if (p0.y < 0.0) {
  3163. currentAttributes = westGeometry.attributes;
  3164. currentIndices = westGeometry.indices;
  3165. } else {
  3166. currentAttributes = eastGeometry.attributes;
  3167. currentIndices = eastGeometry.indices;
  3168. }
  3169. currentAttributes.position.values.push(p0.x, p0.y, p0.z);
  3170. currentAttributes.position.values.push(p0.x, p0.y, p0.z);
  3171. currentAttributes.position.values.push(p2.x, p2.y, p2.z);
  3172. currentAttributes.position.values.push(p2.x, p2.y, p2.z);
  3173. for (j = i * 3; j < i * 3 + 4 * 3; ++j) {
  3174. currentAttributes.prevPosition.values.push(prevPositions[j]);
  3175. currentAttributes.nextPosition.values.push(nextPositions[j]);
  3176. }
  3177. for (j = i * 2; j < i * 2 + 4 * 2; ++j) {
  3178. currentAttributes.expandAndWidth.values.push(expandAndWidths[j]);
  3179. if (when.defined(texCoords)) {
  3180. currentAttributes.st.values.push(texCoords[j]);
  3181. }
  3182. }
  3183. if (when.defined(colors)) {
  3184. for (j = i * 4; j < i * 4 + 4 * 4; ++j) {
  3185. currentAttributes.color.values.push(colors[j]);
  3186. }
  3187. }
  3188. index = currentAttributes.position.values.length / 3 - 4;
  3189. currentIndices.push(index, index + 2, index + 1);
  3190. currentIndices.push(index + 1, index + 2, index + 3);
  3191. }
  3192. }
  3193. if (intersectionFound) {
  3194. updateAdjacencyAfterSplit(westGeometry);
  3195. updateAdjacencyAfterSplit(eastGeometry);
  3196. }
  3197. updateInstanceAfterSplit(instance, westGeometry, eastGeometry);
  3198. }
  3199. /**
  3200. * Splits the instances's geometry, by introducing new vertices and indices,that
  3201. * intersect the International Date Line and Prime Meridian so that no primitives cross longitude
  3202. * -180/180 degrees. This is not required for 3D drawing, but is required for
  3203. * correcting drawing in 2D and Columbus view.
  3204. *
  3205. * @private
  3206. *
  3207. * @param {GeometryInstance} instance The instance to modify.
  3208. * @returns {GeometryInstance} The modified <code>instance</code> argument, with it's geometry split at the International Date Line.
  3209. *
  3210. * @example
  3211. * instance = Cesium.GeometryPipeline.splitLongitude(instance);
  3212. */
  3213. GeometryPipeline.splitLongitude = function (instance) {
  3214. //>>includeStart('debug', pragmas.debug);
  3215. if (!when.defined(instance)) {
  3216. throw new Check.DeveloperError("instance is required.");
  3217. }
  3218. //>>includeEnd('debug');
  3219. var geometry = instance.geometry;
  3220. var boundingSphere = geometry.boundingSphere;
  3221. if (when.defined(boundingSphere)) {
  3222. var minX = boundingSphere.center.x - boundingSphere.radius;
  3223. if (
  3224. minX > 0 ||
  3225. Transforms.BoundingSphere.intersectPlane(boundingSphere, Plane.Plane.ORIGIN_ZX_PLANE) !==
  3226. Transforms.Intersect.INTERSECTING
  3227. ) {
  3228. return instance;
  3229. }
  3230. }
  3231. if (geometry.geometryType !== GeometryAttribute.GeometryType.NONE) {
  3232. switch (geometry.geometryType) {
  3233. case GeometryAttribute.GeometryType.POLYLINES:
  3234. splitLongitudePolyline(instance);
  3235. break;
  3236. case GeometryAttribute.GeometryType.TRIANGLES:
  3237. splitLongitudeTriangles(instance);
  3238. break;
  3239. case GeometryAttribute.GeometryType.LINES:
  3240. splitLongitudeLines(instance);
  3241. break;
  3242. }
  3243. } else {
  3244. indexPrimitive(geometry);
  3245. if (geometry.primitiveType === GeometryAttribute.PrimitiveType.TRIANGLES) {
  3246. splitLongitudeTriangles(instance);
  3247. } else if (geometry.primitiveType === GeometryAttribute.PrimitiveType.LINES) {
  3248. splitLongitudeLines(instance);
  3249. }
  3250. }
  3251. return instance;
  3252. };
  3253. exports.GeometryPipeline = GeometryPipeline;
  3254. });