GeometryPipeline-f0b16df6.js 132 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965
  1. /* This file is automatically rebuilt by the Cesium build process. */
  2. define(['exports', './defined-26bd4a03', './Check-da037458', './defaultValue-f2e68450', './Math-fa6e45cb', './Cartesian2-2a723276', './Transforms-65aba0a4', './ComponentDatatype-69643096', './GeometryAttribute-ed359d71', './AttributeCompression-87682214', './EncodedCartesian3-8b2b90d0', './IndexDatatype-3de60176', './IntersectionTests-c2360ffa', './Plane-a1a3fd52'], function (exports, defined, Check, defaultValue, _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. * @exports barycentricCoordinates
  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 (!defined.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(!defined.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. * @exports 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 = defaultValue.defaultValue(options, defaultValue.defaultValue.EMPTY_OBJECT);
  132. var indices = options.indices;
  133. var maximumIndex = options.maximumIndex;
  134. var cacheSize = defaultValue.defaultValue(options.cacheSize, 24);
  135. //>>includeStart('debug', pragmas.debug);
  136. if (!defined.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 (!defined.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 = defaultValue.defaultValue(options, defaultValue.defaultValue.EMPTY_OBJECT);
  202. var indices = options.indices;
  203. var maximumIndex = options.maximumIndex;
  204. var cacheSize = defaultValue.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(indices, cacheSize, oneRing, vertices, s, deadEnd, maximumIndexPlusOne) {
  225. var n = -1;
  226. var p;
  227. var m = -1;
  228. var itOneRing = 0;
  229. while (itOneRing < oneRing.length) {
  230. var index = oneRing[itOneRing];
  231. if (vertices[index].numLiveTriangles) {
  232. p = 0;
  233. if ((s - vertices[index].timeStamp + (2 * vertices[index].numLiveTriangles)) <= cacheSize) {
  234. p = s - vertices[index].timeStamp;
  235. }
  236. if ((p > m) || (m === -1)) {
  237. m = p;
  238. n = index;
  239. }
  240. }
  241. ++itOneRing;
  242. }
  243. if (n === -1) {
  244. return skipDeadEnd(vertices, deadEnd, indices, maximumIndexPlusOne);
  245. }
  246. return n;
  247. }
  248. //>>includeStart('debug', pragmas.debug);
  249. if (!defined.defined(indices)) {
  250. throw new Check.DeveloperError('indices is required.');
  251. }
  252. //>>includeEnd('debug');
  253. var numIndices = indices.length;
  254. //>>includeStart('debug', pragmas.debug);
  255. if (numIndices < 3 || numIndices % 3 !== 0) {
  256. throw new Check.DeveloperError('indices length must be a multiple of three.');
  257. }
  258. if (maximumIndex <= 0) {
  259. throw new Check.DeveloperError('maximumIndex must be greater than zero.');
  260. }
  261. if (cacheSize < 3) {
  262. throw new Check.DeveloperError('cacheSize must be greater than two.');
  263. }
  264. //>>includeEnd('debug');
  265. // Determine maximum index
  266. var maximumIndexPlusOne = 0;
  267. var currentIndex = 0;
  268. var intoIndices = indices[currentIndex];
  269. var endIndex = numIndices;
  270. if (defined.defined(maximumIndex)) {
  271. maximumIndexPlusOne = maximumIndex + 1;
  272. } else {
  273. while (currentIndex < endIndex) {
  274. if (intoIndices > maximumIndexPlusOne) {
  275. maximumIndexPlusOne = intoIndices;
  276. }
  277. ++currentIndex;
  278. intoIndices = indices[currentIndex];
  279. }
  280. if (maximumIndexPlusOne === -1) {
  281. return 0;
  282. }
  283. ++maximumIndexPlusOne;
  284. }
  285. // Vertices
  286. var vertices = [];
  287. var i;
  288. for (i = 0; i < maximumIndexPlusOne; i++) {
  289. vertices[i] = {
  290. numLiveTriangles : 0,
  291. timeStamp : 0,
  292. vertexTriangles : []
  293. };
  294. }
  295. currentIndex = 0;
  296. var triangle = 0;
  297. while (currentIndex < endIndex) {
  298. vertices[indices[currentIndex]].vertexTriangles.push(triangle);
  299. ++(vertices[indices[currentIndex]]).numLiveTriangles;
  300. vertices[indices[currentIndex + 1]].vertexTriangles.push(triangle);
  301. ++(vertices[indices[currentIndex + 1]]).numLiveTriangles;
  302. vertices[indices[currentIndex + 2]].vertexTriangles.push(triangle);
  303. ++(vertices[indices[currentIndex + 2]]).numLiveTriangles;
  304. ++triangle;
  305. currentIndex += 3;
  306. }
  307. // Starting index
  308. var f = 0;
  309. // Time Stamp
  310. var s = cacheSize + 1;
  311. cursor = 1;
  312. // Process
  313. var oneRing = [];
  314. var deadEnd = []; //Stack
  315. var vertex;
  316. var intoVertices;
  317. var currentOutputIndex = 0;
  318. var outputIndices = [];
  319. var numTriangles = numIndices / 3;
  320. var triangleEmitted = [];
  321. for (i = 0; i < numTriangles; i++) {
  322. triangleEmitted[i] = false;
  323. }
  324. var index;
  325. var limit;
  326. while (f !== -1) {
  327. oneRing = [];
  328. intoVertices = vertices[f];
  329. limit = intoVertices.vertexTriangles.length;
  330. for ( var k = 0; k < limit; ++k) {
  331. triangle = intoVertices.vertexTriangles[k];
  332. if (!triangleEmitted[triangle]) {
  333. triangleEmitted[triangle] = true;
  334. currentIndex = triangle + triangle + triangle;
  335. for ( var j = 0; j < 3; ++j) {
  336. // Set this index as a possible next index
  337. index = indices[currentIndex];
  338. oneRing.push(index);
  339. deadEnd.push(index);
  340. // Output index
  341. outputIndices[currentOutputIndex] = index;
  342. ++currentOutputIndex;
  343. // Cache processing
  344. vertex = vertices[index];
  345. --vertex.numLiveTriangles;
  346. if ((s - vertex.timeStamp) > cacheSize) {
  347. vertex.timeStamp = s;
  348. ++s;
  349. }
  350. ++currentIndex;
  351. }
  352. }
  353. }
  354. f = getNextVertex(indices, cacheSize, oneRing, vertices, s, deadEnd, maximumIndexPlusOne);
  355. }
  356. return outputIndices;
  357. };
  358. /**
  359. * Content pipeline functions for geometries.
  360. *
  361. * @exports GeometryPipeline
  362. *
  363. * @see Geometry
  364. */
  365. var GeometryPipeline = {};
  366. function addTriangle(lines, index, i0, i1, i2) {
  367. lines[index++] = i0;
  368. lines[index++] = i1;
  369. lines[index++] = i1;
  370. lines[index++] = i2;
  371. lines[index++] = i2;
  372. lines[index] = i0;
  373. }
  374. function trianglesToLines(triangles) {
  375. var count = triangles.length;
  376. var size = (count / 3) * 6;
  377. var lines = IndexDatatype.IndexDatatype.createTypedArray(count, size);
  378. var index = 0;
  379. for ( var i = 0; i < count; i += 3, index += 6) {
  380. addTriangle(lines, index, triangles[i], triangles[i + 1], triangles[i + 2]);
  381. }
  382. return lines;
  383. }
  384. function triangleStripToLines(triangles) {
  385. var count = triangles.length;
  386. if (count >= 3) {
  387. var size = (count - 2) * 6;
  388. var lines = IndexDatatype.IndexDatatype.createTypedArray(count, size);
  389. addTriangle(lines, 0, triangles[0], triangles[1], triangles[2]);
  390. var index = 6;
  391. for ( var i = 3; i < count; ++i, index += 6) {
  392. addTriangle(lines, index, triangles[i - 1], triangles[i], triangles[i - 2]);
  393. }
  394. return lines;
  395. }
  396. return new Uint16Array();
  397. }
  398. function triangleFanToLines(triangles) {
  399. if (triangles.length > 0) {
  400. var count = triangles.length - 1;
  401. var size = (count - 1) * 6;
  402. var lines = IndexDatatype.IndexDatatype.createTypedArray(count, size);
  403. var base = triangles[0];
  404. var index = 0;
  405. for ( var i = 1; i < count; ++i, index += 6) {
  406. addTriangle(lines, index, base, triangles[i], triangles[i + 1]);
  407. }
  408. return lines;
  409. }
  410. return new Uint16Array();
  411. }
  412. /**
  413. * Converts a geometry's triangle indices to line indices. If the geometry has an <code>indices</code>
  414. * and its <code>primitiveType</code> is <code>TRIANGLES</code>, <code>TRIANGLE_STRIP</code>,
  415. * <code>TRIANGLE_FAN</code>, it is converted to <code>LINES</code>; otherwise, the geometry is not changed.
  416. * <p>
  417. * This is commonly used to create a wireframe geometry for visual debugging.
  418. * </p>
  419. *
  420. * @param {Geometry} geometry The geometry to modify.
  421. * @returns {Geometry} The modified <code>geometry</code> argument, with its triangle indices converted to lines.
  422. *
  423. * @exception {DeveloperError} geometry.primitiveType must be TRIANGLES, TRIANGLE_STRIP, or TRIANGLE_FAN.
  424. *
  425. * @example
  426. * geometry = Cesium.GeometryPipeline.toWireframe(geometry);
  427. */
  428. GeometryPipeline.toWireframe = function(geometry) {
  429. //>>includeStart('debug', pragmas.debug);
  430. if (!defined.defined(geometry)) {
  431. throw new Check.DeveloperError('geometry is required.');
  432. }
  433. //>>includeEnd('debug');
  434. var indices = geometry.indices;
  435. if (defined.defined(indices)) {
  436. switch (geometry.primitiveType) {
  437. case GeometryAttribute.PrimitiveType.TRIANGLES:
  438. geometry.indices = trianglesToLines(indices);
  439. break;
  440. case GeometryAttribute.PrimitiveType.TRIANGLE_STRIP:
  441. geometry.indices = triangleStripToLines(indices);
  442. break;
  443. case GeometryAttribute.PrimitiveType.TRIANGLE_FAN:
  444. geometry.indices = triangleFanToLines(indices);
  445. break;
  446. //>>includeStart('debug', pragmas.debug);
  447. default:
  448. throw new Check.DeveloperError('geometry.primitiveType must be TRIANGLES, TRIANGLE_STRIP, or TRIANGLE_FAN.');
  449. //>>includeEnd('debug');
  450. }
  451. geometry.primitiveType = GeometryAttribute.PrimitiveType.LINES;
  452. }
  453. return geometry;
  454. };
  455. /**
  456. * Creates a new {@link Geometry} with <code>LINES</code> representing the provided
  457. * attribute (<code>attributeName</code>) for the provided geometry. This is used to
  458. * visualize vector attributes like normals, tangents, and bitangents.
  459. *
  460. * @param {Geometry} geometry The <code>Geometry</code> instance with the attribute.
  461. * @param {String} [attributeName='normal'] The name of the attribute.
  462. * @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.
  463. * @returns {Geometry} A new <code>Geometry</code> instance with line segments for the vector.
  464. *
  465. * @exception {DeveloperError} geometry.attributes must have an attribute with the same name as the attributeName parameter.
  466. *
  467. * @example
  468. * var geometry = Cesium.GeometryPipeline.createLineSegmentsForVectors(instance.geometry, 'bitangent', 100000.0);
  469. */
  470. GeometryPipeline.createLineSegmentsForVectors = function(geometry, attributeName, length) {
  471. attributeName = defaultValue.defaultValue(attributeName, 'normal');
  472. //>>includeStart('debug', pragmas.debug);
  473. if (!defined.defined(geometry)) {
  474. throw new Check.DeveloperError('geometry is required.');
  475. }
  476. if (!defined.defined(geometry.attributes.position)) {
  477. throw new Check.DeveloperError('geometry.attributes.position is required.');
  478. }
  479. if (!defined.defined(geometry.attributes[attributeName])) {
  480. throw new Check.DeveloperError('geometry.attributes must have an attribute with the same name as the attributeName parameter, ' + attributeName + '.');
  481. }
  482. //>>includeEnd('debug');
  483. length = defaultValue.defaultValue(length, 10000.0);
  484. var positions = geometry.attributes.position.values;
  485. var vectors = geometry.attributes[attributeName].values;
  486. var positionsLength = positions.length;
  487. var newPositions = new Float64Array(2 * positionsLength);
  488. var j = 0;
  489. for (var i = 0; i < positionsLength; i += 3) {
  490. newPositions[j++] = positions[i];
  491. newPositions[j++] = positions[i + 1];
  492. newPositions[j++] = positions[i + 2];
  493. newPositions[j++] = positions[i] + (vectors[i] * length);
  494. newPositions[j++] = positions[i + 1] + (vectors[i + 1] * length);
  495. newPositions[j++] = positions[i + 2] + (vectors[i + 2] * length);
  496. }
  497. var newBoundingSphere;
  498. var bs = geometry.boundingSphere;
  499. if (defined.defined(bs)) {
  500. newBoundingSphere = new Transforms.BoundingSphere(bs.center, bs.radius + length);
  501. }
  502. return new GeometryAttribute.Geometry({
  503. attributes : {
  504. position : new GeometryAttribute.GeometryAttribute({
  505. componentDatatype : ComponentDatatype.ComponentDatatype.DOUBLE,
  506. componentsPerAttribute : 3,
  507. values : newPositions
  508. })
  509. },
  510. primitiveType : GeometryAttribute.PrimitiveType.LINES,
  511. boundingSphere : newBoundingSphere
  512. });
  513. };
  514. /**
  515. * Creates an object that maps attribute names to unique locations (indices)
  516. * for matching vertex attributes and shader programs.
  517. *
  518. * @param {Geometry} geometry The geometry, which is not modified, to create the object for.
  519. * @returns {Object} An object with attribute name / index pairs.
  520. *
  521. * @example
  522. * var attributeLocations = Cesium.GeometryPipeline.createAttributeLocations(geometry);
  523. * // Example output
  524. * // {
  525. * // 'position' : 0,
  526. * // 'normal' : 1
  527. * // }
  528. */
  529. GeometryPipeline.createAttributeLocations = function(geometry) {
  530. //>>includeStart('debug', pragmas.debug);
  531. if (!defined.defined(geometry)) {
  532. throw new Check.DeveloperError('geometry is required.');
  533. }
  534. //>>includeEnd('debug')
  535. // There can be a WebGL performance hit when attribute 0 is disabled, so
  536. // assign attribute locations to well-known attributes.
  537. var semantics = [
  538. 'position',
  539. 'positionHigh',
  540. 'positionLow',
  541. // From VertexFormat.position - after 2D projection and high-precision encoding
  542. 'position3DHigh',
  543. 'position3DLow',
  544. 'position2DHigh',
  545. 'position2DLow',
  546. // From Primitive
  547. 'pickColor',
  548. // From VertexFormat
  549. 'normal',
  550. 'st',
  551. 'tangent',
  552. 'bitangent',
  553. // For shadow volumes
  554. 'extrudeDirection',
  555. // From compressing texture coordinates and normals
  556. 'compressedAttributes'
  557. ];
  558. var attributes = geometry.attributes;
  559. var indices = {};
  560. var j = 0;
  561. var i;
  562. var len = semantics.length;
  563. // Attribute locations for well-known attributes
  564. for (i = 0; i < len; ++i) {
  565. var semantic = semantics[i];
  566. if (defined.defined(attributes[semantic])) {
  567. indices[semantic] = j++;
  568. }
  569. }
  570. // Locations for custom attributes
  571. for (var name in attributes) {
  572. if (attributes.hasOwnProperty(name) && (!defined.defined(indices[name]))) {
  573. indices[name] = j++;
  574. }
  575. }
  576. return indices;
  577. };
  578. /**
  579. * Reorders a geometry's attributes and <code>indices</code> to achieve better performance from the GPU's pre-vertex-shader cache.
  580. *
  581. * @param {Geometry} geometry The geometry to modify.
  582. * @returns {Geometry} The modified <code>geometry</code> argument, with its attributes and indices reordered for the GPU's pre-vertex-shader cache.
  583. *
  584. * @exception {DeveloperError} Each attribute array in geometry.attributes must have the same number of attributes.
  585. *
  586. *
  587. * @example
  588. * geometry = Cesium.GeometryPipeline.reorderForPreVertexCache(geometry);
  589. *
  590. * @see GeometryPipeline.reorderForPostVertexCache
  591. */
  592. GeometryPipeline.reorderForPreVertexCache = function(geometry) {
  593. //>>includeStart('debug', pragmas.debug);
  594. if (!defined.defined(geometry)) {
  595. throw new Check.DeveloperError('geometry is required.');
  596. }
  597. //>>includeEnd('debug');
  598. var numVertices = GeometryAttribute.Geometry.computeNumberOfVertices(geometry);
  599. var indices = geometry.indices;
  600. if (defined.defined(indices)) {
  601. var indexCrossReferenceOldToNew = new Int32Array(numVertices);
  602. for ( var i = 0; i < numVertices; i++) {
  603. indexCrossReferenceOldToNew[i] = -1;
  604. }
  605. // Construct cross reference and reorder indices
  606. var indicesIn = indices;
  607. var numIndices = indicesIn.length;
  608. var indicesOut = IndexDatatype.IndexDatatype.createTypedArray(numVertices, numIndices);
  609. var intoIndicesIn = 0;
  610. var intoIndicesOut = 0;
  611. var nextIndex = 0;
  612. var tempIndex;
  613. while (intoIndicesIn < numIndices) {
  614. tempIndex = indexCrossReferenceOldToNew[indicesIn[intoIndicesIn]];
  615. if (tempIndex !== -1) {
  616. indicesOut[intoIndicesOut] = tempIndex;
  617. } else {
  618. tempIndex = indicesIn[intoIndicesIn];
  619. indexCrossReferenceOldToNew[tempIndex] = nextIndex;
  620. indicesOut[intoIndicesOut] = nextIndex;
  621. ++nextIndex;
  622. }
  623. ++intoIndicesIn;
  624. ++intoIndicesOut;
  625. }
  626. geometry.indices = indicesOut;
  627. // Reorder attributes
  628. var attributes = geometry.attributes;
  629. for ( var property in attributes) {
  630. if (attributes.hasOwnProperty(property) &&
  631. defined.defined(attributes[property]) &&
  632. defined.defined(attributes[property].values)) {
  633. var attribute = attributes[property];
  634. var elementsIn = attribute.values;
  635. var intoElementsIn = 0;
  636. var numComponents = attribute.componentsPerAttribute;
  637. var elementsOut = ComponentDatatype.ComponentDatatype.createTypedArray(attribute.componentDatatype, nextIndex * numComponents);
  638. while (intoElementsIn < numVertices) {
  639. var temp = indexCrossReferenceOldToNew[intoElementsIn];
  640. if (temp !== -1) {
  641. for (var j = 0; j < numComponents; j++) {
  642. elementsOut[numComponents * temp + j] = elementsIn[numComponents * intoElementsIn + j];
  643. }
  644. }
  645. ++intoElementsIn;
  646. }
  647. attribute.values = elementsOut;
  648. }
  649. }
  650. }
  651. return geometry;
  652. };
  653. /**
  654. * Reorders a geometry's <code>indices</code> to achieve better performance from the GPU's
  655. * post vertex-shader cache by using the Tipsify algorithm. If the geometry <code>primitiveType</code>
  656. * is not <code>TRIANGLES</code> or the geometry does not have an <code>indices</code>, this function has no effect.
  657. *
  658. * @param {Geometry} geometry The geometry to modify.
  659. * @param {Number} [cacheCapacity=24] The number of vertices that can be held in the GPU's vertex cache.
  660. * @returns {Geometry} The modified <code>geometry</code> argument, with its indices reordered for the post-vertex-shader cache.
  661. *
  662. * @exception {DeveloperError} cacheCapacity must be greater than two.
  663. *
  664. *
  665. * @example
  666. * geometry = Cesium.GeometryPipeline.reorderForPostVertexCache(geometry);
  667. *
  668. * @see GeometryPipeline.reorderForPreVertexCache
  669. * @see {@link http://gfx.cs.princ0eton.edu/pubs/Sander_2007_%3ETR/tipsy.pdf|Fast Triangle Reordering for Vertex Locality and Reduced Overdraw}
  670. * by Sander, Nehab, and Barczak
  671. */
  672. GeometryPipeline.reorderForPostVertexCache = function(geometry, cacheCapacity) {
  673. //>>includeStart('debug', pragmas.debug);
  674. if (!defined.defined(geometry)) {
  675. throw new Check.DeveloperError('geometry is required.');
  676. }
  677. //>>includeEnd('debug');
  678. var indices = geometry.indices;
  679. if ((geometry.primitiveType === GeometryAttribute.PrimitiveType.TRIANGLES) && (defined.defined(indices))) {
  680. var numIndices = indices.length;
  681. var maximumIndex = 0;
  682. for ( var j = 0; j < numIndices; j++) {
  683. if (indices[j] > maximumIndex) {
  684. maximumIndex = indices[j];
  685. }
  686. }
  687. geometry.indices = Tipsify.tipsify({
  688. indices : indices,
  689. maximumIndex : maximumIndex,
  690. cacheSize : cacheCapacity
  691. });
  692. }
  693. return geometry;
  694. };
  695. function copyAttributesDescriptions(attributes) {
  696. var newAttributes = {};
  697. for ( var attribute in attributes) {
  698. if (attributes.hasOwnProperty(attribute) &&
  699. defined.defined(attributes[attribute]) &&
  700. defined.defined(attributes[attribute].values)) {
  701. var attr = attributes[attribute];
  702. newAttributes[attribute] = new GeometryAttribute.GeometryAttribute({
  703. componentDatatype : attr.componentDatatype,
  704. componentsPerAttribute : attr.componentsPerAttribute,
  705. normalize : attr.normalize,
  706. values : []
  707. });
  708. }
  709. }
  710. return newAttributes;
  711. }
  712. function copyVertex(destinationAttributes, sourceAttributes, index) {
  713. for ( var attribute in sourceAttributes) {
  714. if (sourceAttributes.hasOwnProperty(attribute) &&
  715. defined.defined(sourceAttributes[attribute]) &&
  716. defined.defined(sourceAttributes[attribute].values)) {
  717. var attr = sourceAttributes[attribute];
  718. for ( var k = 0; k < attr.componentsPerAttribute; ++k) {
  719. destinationAttributes[attribute].values.push(attr.values[(index * attr.componentsPerAttribute) + k]);
  720. }
  721. }
  722. }
  723. }
  724. /**
  725. * Splits a geometry into multiple geometries, if necessary, to ensure that indices in the
  726. * <code>indices</code> fit into unsigned shorts. This is used to meet the WebGL requirements
  727. * when unsigned int indices are not supported.
  728. * <p>
  729. * If the geometry does not have any <code>indices</code>, this function has no effect.
  730. * </p>
  731. *
  732. * @param {Geometry} geometry The geometry to be split into multiple geometries.
  733. * @returns {Geometry[]} An array of geometries, each with indices that fit into unsigned shorts.
  734. *
  735. * @exception {DeveloperError} geometry.primitiveType must equal to PrimitiveType.TRIANGLES, PrimitiveType.LINES, or PrimitiveType.POINTS
  736. * @exception {DeveloperError} All geometry attribute lists must have the same number of attributes.
  737. *
  738. * @example
  739. * var geometries = Cesium.GeometryPipeline.fitToUnsignedShortIndices(geometry);
  740. */
  741. GeometryPipeline.fitToUnsignedShortIndices = function(geometry) {
  742. //>>includeStart('debug', pragmas.debug);
  743. if (!defined.defined(geometry)) {
  744. throw new Check.DeveloperError('geometry is required.');
  745. }
  746. if ((defined.defined(geometry.indices)) &&
  747. ((geometry.primitiveType !== GeometryAttribute.PrimitiveType.TRIANGLES) &&
  748. (geometry.primitiveType !== GeometryAttribute.PrimitiveType.LINES) &&
  749. (geometry.primitiveType !== GeometryAttribute.PrimitiveType.POINTS))) {
  750. throw new Check.DeveloperError('geometry.primitiveType must equal to PrimitiveType.TRIANGLES, PrimitiveType.LINES, or PrimitiveType.POINTS.');
  751. }
  752. //>>includeEnd('debug');
  753. var geometries = [];
  754. // If there's an index list and more than 64K attributes, it is possible that
  755. // some indices are outside the range of unsigned short [0, 64K - 1]
  756. var numberOfVertices = GeometryAttribute.Geometry.computeNumberOfVertices(geometry);
  757. if (defined.defined(geometry.indices) && (numberOfVertices >= _Math.CesiumMath.SIXTY_FOUR_KILOBYTES)) {
  758. var oldToNewIndex = [];
  759. var newIndices = [];
  760. var currentIndex = 0;
  761. var newAttributes = copyAttributesDescriptions(geometry.attributes);
  762. var originalIndices = geometry.indices;
  763. var numberOfIndices = originalIndices.length;
  764. var indicesPerPrimitive;
  765. if (geometry.primitiveType === GeometryAttribute.PrimitiveType.TRIANGLES) {
  766. indicesPerPrimitive = 3;
  767. } else if (geometry.primitiveType === GeometryAttribute.PrimitiveType.LINES) {
  768. indicesPerPrimitive = 2;
  769. } else if (geometry.primitiveType === GeometryAttribute.PrimitiveType.POINTS) {
  770. indicesPerPrimitive = 1;
  771. }
  772. for ( var j = 0; j < numberOfIndices; j += indicesPerPrimitive) {
  773. for (var k = 0; k < indicesPerPrimitive; ++k) {
  774. var x = originalIndices[j + k];
  775. var i = oldToNewIndex[x];
  776. if (!defined.defined(i)) {
  777. i = currentIndex++;
  778. oldToNewIndex[x] = i;
  779. copyVertex(newAttributes, geometry.attributes, x);
  780. }
  781. newIndices.push(i);
  782. }
  783. if (currentIndex + indicesPerPrimitive >= _Math.CesiumMath.SIXTY_FOUR_KILOBYTES) {
  784. geometries.push(new GeometryAttribute.Geometry({
  785. attributes : newAttributes,
  786. indices : newIndices,
  787. primitiveType : geometry.primitiveType,
  788. boundingSphere : geometry.boundingSphere,
  789. boundingSphereCV : geometry.boundingSphereCV
  790. }));
  791. // Reset for next vertex-array
  792. oldToNewIndex = [];
  793. newIndices = [];
  794. currentIndex = 0;
  795. newAttributes = copyAttributesDescriptions(geometry.attributes);
  796. }
  797. }
  798. if (newIndices.length !== 0) {
  799. geometries.push(new GeometryAttribute.Geometry({
  800. attributes : newAttributes,
  801. indices : newIndices,
  802. primitiveType : geometry.primitiveType,
  803. boundingSphere : geometry.boundingSphere,
  804. boundingSphereCV : geometry.boundingSphereCV
  805. }));
  806. }
  807. } else {
  808. // No need to split into multiple geometries
  809. geometries.push(geometry);
  810. }
  811. return geometries;
  812. };
  813. var scratchProjectTo2DCartesian3 = new Cartesian2.Cartesian3();
  814. var scratchProjectTo2DCartographic = new Cartesian2.Cartographic();
  815. /**
  816. * Projects a geometry's 3D <code>position</code> attribute to 2D, replacing the <code>position</code>
  817. * attribute with separate <code>position3D</code> and <code>position2D</code> attributes.
  818. * <p>
  819. * If the geometry does not have a <code>position</code>, this function has no effect.
  820. * </p>
  821. *
  822. * @param {Geometry} geometry The geometry to modify.
  823. * @param {String} attributeName The name of the attribute.
  824. * @param {String} attributeName3D The name of the attribute in 3D.
  825. * @param {String} attributeName2D The name of the attribute in 2D.
  826. * @param {Object} [projection=new GeographicProjection()] The projection to use.
  827. * @returns {Geometry} The modified <code>geometry</code> argument with <code>position3D</code> and <code>position2D</code> attributes.
  828. *
  829. * @exception {DeveloperError} geometry must have attribute matching the attributeName argument.
  830. * @exception {DeveloperError} The attribute componentDatatype must be ComponentDatatype.DOUBLE.
  831. * @exception {DeveloperError} Could not project a point to 2D.
  832. *
  833. * @example
  834. * geometry = Cesium.GeometryPipeline.projectTo2D(geometry, 'position', 'position3D', 'position2D');
  835. */
  836. GeometryPipeline.projectTo2D = function(geometry, attributeName, attributeName3D, attributeName2D, projection) {
  837. //>>includeStart('debug', pragmas.debug);
  838. if (!defined.defined(geometry)) {
  839. throw new Check.DeveloperError('geometry is required.');
  840. }
  841. if (!defined.defined(attributeName)) {
  842. throw new Check.DeveloperError('attributeName is required.');
  843. }
  844. if (!defined.defined(attributeName3D)) {
  845. throw new Check.DeveloperError('attributeName3D is required.');
  846. }
  847. if (!defined.defined(attributeName2D)) {
  848. throw new Check.DeveloperError('attributeName2D is required.');
  849. }
  850. if (!defined.defined(geometry.attributes[attributeName])) {
  851. throw new Check.DeveloperError('geometry must have attribute matching the attributeName argument: ' + attributeName + '.');
  852. }
  853. if (geometry.attributes[attributeName].componentDatatype !== ComponentDatatype.ComponentDatatype.DOUBLE) {
  854. throw new Check.DeveloperError('The attribute componentDatatype must be ComponentDatatype.DOUBLE.');
  855. }
  856. //>>includeEnd('debug');
  857. var attribute = geometry.attributes[attributeName];
  858. projection = (defined.defined(projection)) ? projection : new Transforms.GeographicProjection();
  859. var ellipsoid = projection.ellipsoid;
  860. // Project original values to 2D.
  861. var values3D = attribute.values;
  862. var projectedValues = new Float64Array(values3D.length);
  863. var index = 0;
  864. for ( var i = 0; i < values3D.length; i += 3) {
  865. var value = Cartesian2.Cartesian3.fromArray(values3D, i, scratchProjectTo2DCartesian3);
  866. var lonLat = ellipsoid.cartesianToCartographic(value, scratchProjectTo2DCartographic);
  867. //>>includeStart('debug', pragmas.debug);
  868. if (!defined.defined(lonLat)) {
  869. throw new Check.DeveloperError('Could not project point (' + value.x + ', ' + value.y + ', ' + value.z + ') to 2D.');
  870. }
  871. //>>includeEnd('debug');
  872. var projectedLonLat = projection.project(lonLat, scratchProjectTo2DCartesian3);
  873. projectedValues[index++] = projectedLonLat.x;
  874. projectedValues[index++] = projectedLonLat.y;
  875. projectedValues[index++] = projectedLonLat.z;
  876. }
  877. // Rename original cartesians to WGS84 cartesians.
  878. geometry.attributes[attributeName3D] = attribute;
  879. // Replace original cartesians with 2D projected cartesians
  880. geometry.attributes[attributeName2D] = new GeometryAttribute.GeometryAttribute({
  881. componentDatatype : ComponentDatatype.ComponentDatatype.DOUBLE,
  882. componentsPerAttribute : 3,
  883. values : projectedValues
  884. });
  885. delete geometry.attributes[attributeName];
  886. return geometry;
  887. };
  888. var encodedResult = {
  889. high : 0.0,
  890. low : 0.0
  891. };
  892. /**
  893. * Encodes floating-point geometry attribute values as two separate attributes to improve
  894. * rendering precision.
  895. * <p>
  896. * This is commonly used to create high-precision position vertex attributes.
  897. * </p>
  898. *
  899. * @param {Geometry} geometry The geometry to modify.
  900. * @param {String} attributeName The name of the attribute.
  901. * @param {String} attributeHighName The name of the attribute for the encoded high bits.
  902. * @param {String} attributeLowName The name of the attribute for the encoded low bits.
  903. * @returns {Geometry} The modified <code>geometry</code> argument, with its encoded attribute.
  904. *
  905. * @exception {DeveloperError} geometry must have attribute matching the attributeName argument.
  906. * @exception {DeveloperError} The attribute componentDatatype must be ComponentDatatype.DOUBLE.
  907. *
  908. * @example
  909. * geometry = Cesium.GeometryPipeline.encodeAttribute(geometry, 'position3D', 'position3DHigh', 'position3DLow');
  910. */
  911. GeometryPipeline.encodeAttribute = function(geometry, attributeName, attributeHighName, attributeLowName) {
  912. //>>includeStart('debug', pragmas.debug);
  913. if (!defined.defined(geometry)) {
  914. throw new Check.DeveloperError('geometry is required.');
  915. }
  916. if (!defined.defined(attributeName)) {
  917. throw new Check.DeveloperError('attributeName is required.');
  918. }
  919. if (!defined.defined(attributeHighName)) {
  920. throw new Check.DeveloperError('attributeHighName is required.');
  921. }
  922. if (!defined.defined(attributeLowName)) {
  923. throw new Check.DeveloperError('attributeLowName is required.');
  924. }
  925. if (!defined.defined(geometry.attributes[attributeName])) {
  926. throw new Check.DeveloperError('geometry must have attribute matching the attributeName argument: ' + attributeName + '.');
  927. }
  928. if (geometry.attributes[attributeName].componentDatatype !== ComponentDatatype.ComponentDatatype.DOUBLE) {
  929. throw new Check.DeveloperError('The attribute componentDatatype must be ComponentDatatype.DOUBLE.');
  930. }
  931. //>>includeEnd('debug');
  932. var attribute = geometry.attributes[attributeName];
  933. var values = attribute.values;
  934. var length = values.length;
  935. var highValues = new Float32Array(length);
  936. var lowValues = new Float32Array(length);
  937. for (var i = 0; i < length; ++i) {
  938. EncodedCartesian3.EncodedCartesian3.encode(values[i], encodedResult);
  939. highValues[i] = encodedResult.high;
  940. lowValues[i] = encodedResult.low;
  941. }
  942. var componentsPerAttribute = attribute.componentsPerAttribute;
  943. geometry.attributes[attributeHighName] = new GeometryAttribute.GeometryAttribute({
  944. componentDatatype : ComponentDatatype.ComponentDatatype.FLOAT,
  945. componentsPerAttribute : componentsPerAttribute,
  946. values : highValues
  947. });
  948. geometry.attributes[attributeLowName] = new GeometryAttribute.GeometryAttribute({
  949. componentDatatype : ComponentDatatype.ComponentDatatype.FLOAT,
  950. componentsPerAttribute : componentsPerAttribute,
  951. values : lowValues
  952. });
  953. delete geometry.attributes[attributeName];
  954. return geometry;
  955. };
  956. var scratchCartesian3$1 = new Cartesian2.Cartesian3();
  957. function transformPoint(matrix, attribute) {
  958. if (defined.defined(attribute)) {
  959. var values = attribute.values;
  960. var length = values.length;
  961. for (var i = 0; i < length; i += 3) {
  962. Cartesian2.Cartesian3.unpack(values, i, scratchCartesian3$1);
  963. Transforms.Matrix4.multiplyByPoint(matrix, scratchCartesian3$1, scratchCartesian3$1);
  964. Cartesian2.Cartesian3.pack(scratchCartesian3$1, values, i);
  965. }
  966. }
  967. }
  968. function transformVector(matrix, attribute) {
  969. if (defined.defined(attribute)) {
  970. var values = attribute.values;
  971. var length = values.length;
  972. for (var i = 0; i < length; i += 3) {
  973. Cartesian2.Cartesian3.unpack(values, i, scratchCartesian3$1);
  974. Transforms.Matrix3.multiplyByVector(matrix, scratchCartesian3$1, scratchCartesian3$1);
  975. scratchCartesian3$1 = Cartesian2.Cartesian3.normalize(scratchCartesian3$1, scratchCartesian3$1);
  976. Cartesian2.Cartesian3.pack(scratchCartesian3$1, values, i);
  977. }
  978. }
  979. }
  980. var inverseTranspose = new Transforms.Matrix4();
  981. var normalMatrix = new Transforms.Matrix3();
  982. /**
  983. * Transforms a geometry instance to world coordinates. This changes
  984. * the instance's <code>modelMatrix</code> to {@link Matrix4.IDENTITY} and transforms the
  985. * following attributes if they are present: <code>position</code>, <code>normal</code>,
  986. * <code>tangent</code>, and <code>bitangent</code>.
  987. *
  988. * @param {GeometryInstance} instance The geometry instance to modify.
  989. * @returns {GeometryInstance} The modified <code>instance</code> argument, with its attributes transforms to world coordinates.
  990. *
  991. * @example
  992. * Cesium.GeometryPipeline.transformToWorldCoordinates(instance);
  993. */
  994. GeometryPipeline.transformToWorldCoordinates = function(instance) {
  995. //>>includeStart('debug', pragmas.debug);
  996. if (!defined.defined(instance)) {
  997. throw new Check.DeveloperError('instance is required.');
  998. }
  999. //>>includeEnd('debug');
  1000. var modelMatrix = instance.modelMatrix;
  1001. if (Transforms.Matrix4.equals(modelMatrix, Transforms.Matrix4.IDENTITY)) {
  1002. // Already in world coordinates
  1003. return instance;
  1004. }
  1005. var attributes = instance.geometry.attributes;
  1006. // Transform attributes in known vertex formats
  1007. transformPoint(modelMatrix, attributes.position);
  1008. transformPoint(modelMatrix, attributes.prevPosition);
  1009. transformPoint(modelMatrix, attributes.nextPosition);
  1010. if ((defined.defined(attributes.normal)) ||
  1011. (defined.defined(attributes.tangent)) ||
  1012. (defined.defined(attributes.bitangent))) {
  1013. Transforms.Matrix4.inverse(modelMatrix, inverseTranspose);
  1014. Transforms.Matrix4.transpose(inverseTranspose, inverseTranspose);
  1015. Transforms.Matrix4.getMatrix3(inverseTranspose, normalMatrix);
  1016. transformVector(normalMatrix, attributes.normal);
  1017. transformVector(normalMatrix, attributes.tangent);
  1018. transformVector(normalMatrix, attributes.bitangent);
  1019. }
  1020. var boundingSphere = instance.geometry.boundingSphere;
  1021. if (defined.defined(boundingSphere)) {
  1022. instance.geometry.boundingSphere = Transforms.BoundingSphere.transform(boundingSphere, modelMatrix, boundingSphere);
  1023. }
  1024. instance.modelMatrix = Transforms.Matrix4.clone(Transforms.Matrix4.IDENTITY);
  1025. return instance;
  1026. };
  1027. function findAttributesInAllGeometries(instances, propertyName) {
  1028. var length = instances.length;
  1029. var attributesInAllGeometries = {};
  1030. var attributes0 = instances[0][propertyName].attributes;
  1031. var name;
  1032. for (name in attributes0) {
  1033. if (attributes0.hasOwnProperty(name) &&
  1034. defined.defined(attributes0[name]) &&
  1035. defined.defined(attributes0[name].values)) {
  1036. var attribute = attributes0[name];
  1037. var numberOfComponents = attribute.values.length;
  1038. var inAllGeometries = true;
  1039. // Does this same attribute exist in all geometries?
  1040. for (var i = 1; i < length; ++i) {
  1041. var otherAttribute = instances[i][propertyName].attributes[name];
  1042. if ((!defined.defined(otherAttribute)) ||
  1043. (attribute.componentDatatype !== otherAttribute.componentDatatype) ||
  1044. (attribute.componentsPerAttribute !== otherAttribute.componentsPerAttribute) ||
  1045. (attribute.normalize !== otherAttribute.normalize)) {
  1046. inAllGeometries = false;
  1047. break;
  1048. }
  1049. numberOfComponents += otherAttribute.values.length;
  1050. }
  1051. if (inAllGeometries) {
  1052. attributesInAllGeometries[name] = new GeometryAttribute.GeometryAttribute({
  1053. componentDatatype : attribute.componentDatatype,
  1054. componentsPerAttribute : attribute.componentsPerAttribute,
  1055. normalize : attribute.normalize,
  1056. values : ComponentDatatype.ComponentDatatype.createTypedArray(attribute.componentDatatype, numberOfComponents)
  1057. });
  1058. }
  1059. }
  1060. }
  1061. return attributesInAllGeometries;
  1062. }
  1063. var tempScratch = new Cartesian2.Cartesian3();
  1064. function combineGeometries(instances, propertyName) {
  1065. var length = instances.length;
  1066. var name;
  1067. var i;
  1068. var j;
  1069. var k;
  1070. var m = instances[0].modelMatrix;
  1071. var haveIndices = (defined.defined(instances[0][propertyName].indices));
  1072. var primitiveType = instances[0][propertyName].primitiveType;
  1073. //>>includeStart('debug', pragmas.debug);
  1074. for (i = 1; i < length; ++i) {
  1075. if (!Transforms.Matrix4.equals(instances[i].modelMatrix, m)) {
  1076. throw new Check.DeveloperError('All instances must have the same modelMatrix.');
  1077. }
  1078. if ((defined.defined(instances[i][propertyName].indices)) !== haveIndices) {
  1079. throw new Check.DeveloperError('All instance geometries must have an indices or not have one.');
  1080. }
  1081. if (instances[i][propertyName].primitiveType !== primitiveType) {
  1082. throw new Check.DeveloperError('All instance geometries must have the same primitiveType.');
  1083. }
  1084. }
  1085. //>>includeEnd('debug');
  1086. // Find subset of attributes in all geometries
  1087. var attributes = findAttributesInAllGeometries(instances, propertyName);
  1088. var values;
  1089. var sourceValues;
  1090. var sourceValuesLength;
  1091. // Combine attributes from each geometry into a single typed array
  1092. for (name in attributes) {
  1093. if (attributes.hasOwnProperty(name)) {
  1094. values = attributes[name].values;
  1095. k = 0;
  1096. for (i = 0; i < length; ++i) {
  1097. sourceValues = instances[i][propertyName].attributes[name].values;
  1098. sourceValuesLength = sourceValues.length;
  1099. for (j = 0; j < sourceValuesLength; ++j) {
  1100. values[k++] = sourceValues[j];
  1101. }
  1102. }
  1103. }
  1104. }
  1105. // Combine index lists
  1106. var indices;
  1107. if (haveIndices) {
  1108. var numberOfIndices = 0;
  1109. for (i = 0; i < length; ++i) {
  1110. numberOfIndices += instances[i][propertyName].indices.length;
  1111. }
  1112. var numberOfVertices = GeometryAttribute.Geometry.computeNumberOfVertices(new GeometryAttribute.Geometry({
  1113. attributes : attributes,
  1114. primitiveType : GeometryAttribute.PrimitiveType.POINTS
  1115. }));
  1116. var destIndices = IndexDatatype.IndexDatatype.createTypedArray(numberOfVertices, numberOfIndices);
  1117. var destOffset = 0;
  1118. var offset = 0;
  1119. for (i = 0; i < length; ++i) {
  1120. var sourceIndices = instances[i][propertyName].indices;
  1121. var sourceIndicesLen = sourceIndices.length;
  1122. for (k = 0; k < sourceIndicesLen; ++k) {
  1123. destIndices[destOffset++] = offset + sourceIndices[k];
  1124. }
  1125. offset += GeometryAttribute.Geometry.computeNumberOfVertices(instances[i][propertyName]);
  1126. }
  1127. indices = destIndices;
  1128. }
  1129. // Create bounding sphere that includes all instances
  1130. var center = new Cartesian2.Cartesian3();
  1131. var radius = 0.0;
  1132. var bs;
  1133. for (i = 0; i < length; ++i) {
  1134. bs = instances[i][propertyName].boundingSphere;
  1135. if (!defined.defined(bs)) {
  1136. // If any geometries have an undefined bounding sphere, then so does the combined geometry
  1137. center = undefined;
  1138. break;
  1139. }
  1140. Cartesian2.Cartesian3.add(bs.center, center, center);
  1141. }
  1142. if (defined.defined(center)) {
  1143. Cartesian2.Cartesian3.divideByScalar(center, length, center);
  1144. for (i = 0; i < length; ++i) {
  1145. bs = instances[i][propertyName].boundingSphere;
  1146. var tempRadius = Cartesian2.Cartesian3.magnitude(Cartesian2.Cartesian3.subtract(bs.center, center, tempScratch)) + bs.radius;
  1147. if (tempRadius > radius) {
  1148. radius = tempRadius;
  1149. }
  1150. }
  1151. }
  1152. return new GeometryAttribute.Geometry({
  1153. attributes : attributes,
  1154. indices : indices,
  1155. primitiveType : primitiveType,
  1156. boundingSphere : (defined.defined(center)) ? new Transforms.BoundingSphere(center, radius) : undefined
  1157. });
  1158. }
  1159. /**
  1160. * Combines geometry from several {@link GeometryInstance} objects into one geometry.
  1161. * This concatenates the attributes, concatenates and adjusts the indices, and creates
  1162. * a bounding sphere encompassing all instances.
  1163. * <p>
  1164. * If the instances do not have the same attributes, a subset of attributes common
  1165. * to all instances is used, and the others are ignored.
  1166. * </p>
  1167. * <p>
  1168. * This is used by {@link Primitive} to efficiently render a large amount of static data.
  1169. * </p>
  1170. *
  1171. * @private
  1172. *
  1173. * @param {GeometryInstance[]} [instances] The array of {@link GeometryInstance} objects whose geometry will be combined.
  1174. * @returns {Geometry} A single geometry created from the provided geometry instances.
  1175. *
  1176. * @exception {DeveloperError} All instances must have the same modelMatrix.
  1177. * @exception {DeveloperError} All instance geometries must have an indices or not have one.
  1178. * @exception {DeveloperError} All instance geometries must have the same primitiveType.
  1179. *
  1180. *
  1181. * @example
  1182. * for (var i = 0; i < instances.length; ++i) {
  1183. * Cesium.GeometryPipeline.transformToWorldCoordinates(instances[i]);
  1184. * }
  1185. * var geometries = Cesium.GeometryPipeline.combineInstances(instances);
  1186. *
  1187. * @see GeometryPipeline.transformToWorldCoordinates
  1188. */
  1189. GeometryPipeline.combineInstances = function(instances) {
  1190. //>>includeStart('debug', pragmas.debug);
  1191. if ((!defined.defined(instances)) || (instances.length < 1)) {
  1192. throw new Check.DeveloperError('instances is required and must have length greater than zero.');
  1193. }
  1194. //>>includeEnd('debug');
  1195. var instanceGeometry = [];
  1196. var instanceSplitGeometry = [];
  1197. var length = instances.length;
  1198. for (var i = 0; i < length; ++i) {
  1199. var instance = instances[i];
  1200. if (defined.defined(instance.geometry)) {
  1201. instanceGeometry.push(instance);
  1202. } else if (defined.defined(instance.westHemisphereGeometry) && defined.defined(instance.eastHemisphereGeometry)) {
  1203. instanceSplitGeometry.push(instance);
  1204. }
  1205. }
  1206. var geometries = [];
  1207. if (instanceGeometry.length > 0) {
  1208. geometries.push(combineGeometries(instanceGeometry, 'geometry'));
  1209. }
  1210. if (instanceSplitGeometry.length > 0) {
  1211. geometries.push(combineGeometries(instanceSplitGeometry, 'westHemisphereGeometry'));
  1212. geometries.push(combineGeometries(instanceSplitGeometry, 'eastHemisphereGeometry'));
  1213. }
  1214. return geometries;
  1215. };
  1216. var normal = new Cartesian2.Cartesian3();
  1217. var v0 = new Cartesian2.Cartesian3();
  1218. var v1 = new Cartesian2.Cartesian3();
  1219. var v2 = new Cartesian2.Cartesian3();
  1220. /**
  1221. * Computes per-vertex normals for a geometry containing <code>TRIANGLES</code> by averaging the normals of
  1222. * all triangles incident to the vertex. The result is a new <code>normal</code> attribute added to the geometry.
  1223. * This assumes a counter-clockwise winding order.
  1224. *
  1225. * @param {Geometry} geometry The geometry to modify.
  1226. * @returns {Geometry} The modified <code>geometry</code> argument with the computed <code>normal</code> attribute.
  1227. *
  1228. * @exception {DeveloperError} geometry.indices length must be greater than 0 and be a multiple of 3.
  1229. * @exception {DeveloperError} geometry.primitiveType must be {@link PrimitiveType.TRIANGLES}.
  1230. *
  1231. * @example
  1232. * Cesium.GeometryPipeline.computeNormal(geometry);
  1233. */
  1234. GeometryPipeline.computeNormal = function(geometry) {
  1235. //>>includeStart('debug', pragmas.debug);
  1236. if (!defined.defined(geometry)) {
  1237. throw new Check.DeveloperError('geometry is required.');
  1238. }
  1239. if (!defined.defined(geometry.attributes.position) || !defined.defined(geometry.attributes.position.values)) {
  1240. throw new Check.DeveloperError('geometry.attributes.position.values is required.');
  1241. }
  1242. if (!defined.defined(geometry.indices)) {
  1243. throw new Check.DeveloperError('geometry.indices is required.');
  1244. }
  1245. if (geometry.indices.length < 2 || geometry.indices.length % 3 !== 0) {
  1246. throw new Check.DeveloperError('geometry.indices length must be greater than 0 and be a multiple of 3.');
  1247. }
  1248. if (geometry.primitiveType !== GeometryAttribute.PrimitiveType.TRIANGLES) {
  1249. throw new Check.DeveloperError('geometry.primitiveType must be PrimitiveType.TRIANGLES.');
  1250. }
  1251. //>>includeEnd('debug');
  1252. var indices = geometry.indices;
  1253. var attributes = geometry.attributes;
  1254. var vertices = attributes.position.values;
  1255. var numVertices = attributes.position.values.length / 3;
  1256. var numIndices = indices.length;
  1257. var normalsPerVertex = new Array(numVertices);
  1258. var normalsPerTriangle = new Array(numIndices / 3);
  1259. var normalIndices = new Array(numIndices);
  1260. var i;
  1261. for ( i = 0; i < numVertices; i++) {
  1262. normalsPerVertex[i] = {
  1263. indexOffset : 0,
  1264. count : 0,
  1265. currentCount : 0
  1266. };
  1267. }
  1268. var j = 0;
  1269. for (i = 0; i < numIndices; i += 3) {
  1270. var i0 = indices[i];
  1271. var i1 = indices[i + 1];
  1272. var i2 = indices[i + 2];
  1273. var i03 = i0 * 3;
  1274. var i13 = i1 * 3;
  1275. var i23 = i2 * 3;
  1276. v0.x = vertices[i03];
  1277. v0.y = vertices[i03 + 1];
  1278. v0.z = vertices[i03 + 2];
  1279. v1.x = vertices[i13];
  1280. v1.y = vertices[i13 + 1];
  1281. v1.z = vertices[i13 + 2];
  1282. v2.x = vertices[i23];
  1283. v2.y = vertices[i23 + 1];
  1284. v2.z = vertices[i23 + 2];
  1285. normalsPerVertex[i0].count++;
  1286. normalsPerVertex[i1].count++;
  1287. normalsPerVertex[i2].count++;
  1288. Cartesian2.Cartesian3.subtract(v1, v0, v1);
  1289. Cartesian2.Cartesian3.subtract(v2, v0, v2);
  1290. normalsPerTriangle[j] = Cartesian2.Cartesian3.cross(v1, v2, new Cartesian2.Cartesian3());
  1291. j++;
  1292. }
  1293. var indexOffset = 0;
  1294. for (i = 0; i < numVertices; i++) {
  1295. normalsPerVertex[i].indexOffset += indexOffset;
  1296. indexOffset += normalsPerVertex[i].count;
  1297. }
  1298. j = 0;
  1299. var vertexNormalData;
  1300. for (i = 0; i < numIndices; i += 3) {
  1301. vertexNormalData = normalsPerVertex[indices[i]];
  1302. var index = vertexNormalData.indexOffset + vertexNormalData.currentCount;
  1303. normalIndices[index] = j;
  1304. vertexNormalData.currentCount++;
  1305. vertexNormalData = normalsPerVertex[indices[i + 1]];
  1306. index = vertexNormalData.indexOffset + vertexNormalData.currentCount;
  1307. normalIndices[index] = j;
  1308. vertexNormalData.currentCount++;
  1309. vertexNormalData = normalsPerVertex[indices[i + 2]];
  1310. index = vertexNormalData.indexOffset + vertexNormalData.currentCount;
  1311. normalIndices[index] = j;
  1312. vertexNormalData.currentCount++;
  1313. j++;
  1314. }
  1315. var normalValues = new Float32Array(numVertices * 3);
  1316. for (i = 0; i < numVertices; i++) {
  1317. var i3 = i * 3;
  1318. vertexNormalData = normalsPerVertex[i];
  1319. Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.ZERO, normal);
  1320. if (vertexNormalData.count > 0) {
  1321. for (j = 0; j < vertexNormalData.count; j++) {
  1322. Cartesian2.Cartesian3.add(normal, normalsPerTriangle[normalIndices[vertexNormalData.indexOffset + j]], normal);
  1323. }
  1324. // We can run into an issue where a vertex is used with 2 primitives that have opposite winding order.
  1325. if (Cartesian2.Cartesian3.equalsEpsilon(Cartesian2.Cartesian3.ZERO, normal, _Math.CesiumMath.EPSILON10)) {
  1326. Cartesian2.Cartesian3.clone(normalsPerTriangle[normalIndices[vertexNormalData.indexOffset]], normal);
  1327. }
  1328. }
  1329. // We end up with a zero vector probably because of a degenerate triangle
  1330. if (Cartesian2.Cartesian3.equalsEpsilon(Cartesian2.Cartesian3.ZERO, normal, _Math.CesiumMath.EPSILON10)) {
  1331. // Default to (0,0,1)
  1332. normal.z = 1.0;
  1333. }
  1334. Cartesian2.Cartesian3.normalize(normal, normal);
  1335. normalValues[i3] = normal.x;
  1336. normalValues[i3 + 1] = normal.y;
  1337. normalValues[i3 + 2] = normal.z;
  1338. }
  1339. geometry.attributes.normal = new GeometryAttribute.GeometryAttribute({
  1340. componentDatatype : ComponentDatatype.ComponentDatatype.FLOAT,
  1341. componentsPerAttribute : 3,
  1342. values : normalValues
  1343. });
  1344. return geometry;
  1345. };
  1346. var normalScratch = new Cartesian2.Cartesian3();
  1347. var normalScale = new Cartesian2.Cartesian3();
  1348. var tScratch = new Cartesian2.Cartesian3();
  1349. /**
  1350. * Computes per-vertex tangents and bitangents for a geometry containing <code>TRIANGLES</code>.
  1351. * The result is new <code>tangent</code> and <code>bitangent</code> attributes added to the geometry.
  1352. * This assumes a counter-clockwise winding order.
  1353. * <p>
  1354. * Based on <a href="http://www.terathon.com/code/tangent.html">Computing Tangent Space Basis Vectors
  1355. * for an Arbitrary Mesh</a> by Eric Lengyel.
  1356. * </p>
  1357. *
  1358. * @param {Geometry} geometry The geometry to modify.
  1359. * @returns {Geometry} The modified <code>geometry</code> argument with the computed <code>tangent</code> and <code>bitangent</code> attributes.
  1360. *
  1361. * @exception {DeveloperError} geometry.indices length must be greater than 0 and be a multiple of 3.
  1362. * @exception {DeveloperError} geometry.primitiveType must be {@link PrimitiveType.TRIANGLES}.
  1363. *
  1364. * @example
  1365. * Cesium.GeometryPipeline.computeTangentAndBiTangent(geometry);
  1366. */
  1367. GeometryPipeline.computeTangentAndBitangent = function(geometry) {
  1368. //>>includeStart('debug', pragmas.debug);
  1369. if (!defined.defined(geometry)) {
  1370. throw new Check.DeveloperError('geometry is required.');
  1371. }
  1372. //>>includeEnd('debug');
  1373. var attributes = geometry.attributes;
  1374. var indices = geometry.indices;
  1375. //>>includeStart('debug', pragmas.debug);
  1376. if (!defined.defined(attributes.position) || !defined.defined(attributes.position.values)) {
  1377. throw new Check.DeveloperError('geometry.attributes.position.values is required.');
  1378. }
  1379. if (!defined.defined(attributes.normal) || !defined.defined(attributes.normal.values)) {
  1380. throw new Check.DeveloperError('geometry.attributes.normal.values is required.');
  1381. }
  1382. if (!defined.defined(attributes.st) || !defined.defined(attributes.st.values)) {
  1383. throw new Check.DeveloperError('geometry.attributes.st.values is required.');
  1384. }
  1385. if (!defined.defined(indices)) {
  1386. throw new Check.DeveloperError('geometry.indices is required.');
  1387. }
  1388. if (indices.length < 2 || indices.length % 3 !== 0) {
  1389. throw new Check.DeveloperError('geometry.indices length must be greater than 0 and be a multiple of 3.');
  1390. }
  1391. if (geometry.primitiveType !== GeometryAttribute.PrimitiveType.TRIANGLES) {
  1392. throw new Check.DeveloperError('geometry.primitiveType must be PrimitiveType.TRIANGLES.');
  1393. }
  1394. //>>includeEnd('debug');
  1395. var vertices = geometry.attributes.position.values;
  1396. var normals = geometry.attributes.normal.values;
  1397. var st = geometry.attributes.st.values;
  1398. var numVertices = geometry.attributes.position.values.length / 3;
  1399. var numIndices = indices.length;
  1400. var tan1 = new Array(numVertices * 3);
  1401. var i;
  1402. for ( i = 0; i < tan1.length; i++) {
  1403. tan1[i] = 0;
  1404. }
  1405. var i03;
  1406. var i13;
  1407. var i23;
  1408. for (i = 0; i < numIndices; i += 3) {
  1409. var i0 = indices[i];
  1410. var i1 = indices[i + 1];
  1411. var i2 = indices[i + 2];
  1412. i03 = i0 * 3;
  1413. i13 = i1 * 3;
  1414. i23 = i2 * 3;
  1415. var i02 = i0 * 2;
  1416. var i12 = i1 * 2;
  1417. var i22 = i2 * 2;
  1418. var ux = vertices[i03];
  1419. var uy = vertices[i03 + 1];
  1420. var uz = vertices[i03 + 2];
  1421. var wx = st[i02];
  1422. var wy = st[i02 + 1];
  1423. var t1 = st[i12 + 1] - wy;
  1424. var t2 = st[i22 + 1] - wy;
  1425. var r = 1.0 / ((st[i12] - wx) * t2 - (st[i22] - wx) * t1);
  1426. var sdirx = (t2 * (vertices[i13] - ux) - t1 * (vertices[i23] - ux)) * r;
  1427. var sdiry = (t2 * (vertices[i13 + 1] - uy) - t1 * (vertices[i23 + 1] - uy)) * r;
  1428. var sdirz = (t2 * (vertices[i13 + 2] - uz) - t1 * (vertices[i23 + 2] - uz)) * r;
  1429. tan1[i03] += sdirx;
  1430. tan1[i03 + 1] += sdiry;
  1431. tan1[i03 + 2] += sdirz;
  1432. tan1[i13] += sdirx;
  1433. tan1[i13 + 1] += sdiry;
  1434. tan1[i13 + 2] += sdirz;
  1435. tan1[i23] += sdirx;
  1436. tan1[i23 + 1] += sdiry;
  1437. tan1[i23 + 2] += sdirz;
  1438. }
  1439. var tangentValues = new Float32Array(numVertices * 3);
  1440. var bitangentValues = new Float32Array(numVertices * 3);
  1441. for (i = 0; i < numVertices; i++) {
  1442. i03 = i * 3;
  1443. i13 = i03 + 1;
  1444. i23 = i03 + 2;
  1445. var n = Cartesian2.Cartesian3.fromArray(normals, i03, normalScratch);
  1446. var t = Cartesian2.Cartesian3.fromArray(tan1, i03, tScratch);
  1447. var scalar = Cartesian2.Cartesian3.dot(n, t);
  1448. Cartesian2.Cartesian3.multiplyByScalar(n, scalar, normalScale);
  1449. Cartesian2.Cartesian3.normalize(Cartesian2.Cartesian3.subtract(t, normalScale, t), t);
  1450. tangentValues[i03] = t.x;
  1451. tangentValues[i13] = t.y;
  1452. tangentValues[i23] = t.z;
  1453. Cartesian2.Cartesian3.normalize(Cartesian2.Cartesian3.cross(n, t, t), t);
  1454. bitangentValues[i03] = t.x;
  1455. bitangentValues[i13] = t.y;
  1456. bitangentValues[i23] = t.z;
  1457. }
  1458. geometry.attributes.tangent = new GeometryAttribute.GeometryAttribute({
  1459. componentDatatype : ComponentDatatype.ComponentDatatype.FLOAT,
  1460. componentsPerAttribute : 3,
  1461. values : tangentValues
  1462. });
  1463. geometry.attributes.bitangent = new GeometryAttribute.GeometryAttribute({
  1464. componentDatatype : ComponentDatatype.ComponentDatatype.FLOAT,
  1465. componentsPerAttribute : 3,
  1466. values : bitangentValues
  1467. });
  1468. return geometry;
  1469. };
  1470. var scratchCartesian2$1 = new Cartesian2.Cartesian2();
  1471. var toEncode1 = new Cartesian2.Cartesian3();
  1472. var toEncode2 = new Cartesian2.Cartesian3();
  1473. var toEncode3 = new Cartesian2.Cartesian3();
  1474. var encodeResult2 = new Cartesian2.Cartesian2();
  1475. /**
  1476. * Compresses and packs geometry normal attribute values to save memory.
  1477. *
  1478. * @param {Geometry} geometry The geometry to modify.
  1479. * @returns {Geometry} The modified <code>geometry</code> argument, with its normals compressed and packed.
  1480. *
  1481. * @example
  1482. * geometry = Cesium.GeometryPipeline.compressVertices(geometry);
  1483. */
  1484. GeometryPipeline.compressVertices = function(geometry) {
  1485. //>>includeStart('debug', pragmas.debug);
  1486. if (!defined.defined(geometry)) {
  1487. throw new Check.DeveloperError('geometry is required.');
  1488. }
  1489. //>>includeEnd('debug');
  1490. var extrudeAttribute = geometry.attributes.extrudeDirection;
  1491. var i;
  1492. var numVertices;
  1493. if (defined.defined(extrudeAttribute)) {
  1494. //only shadow volumes use extrudeDirection, and shadow volumes use vertexFormat: POSITION_ONLY so we don't need to check other attributes
  1495. var extrudeDirections = extrudeAttribute.values;
  1496. numVertices = extrudeDirections.length / 3.0;
  1497. var compressedDirections = new Float32Array(numVertices * 2);
  1498. var i2 = 0;
  1499. for (i = 0; i < numVertices; ++i) {
  1500. Cartesian2.Cartesian3.fromArray(extrudeDirections, i * 3.0, toEncode1);
  1501. if (Cartesian2.Cartesian3.equals(toEncode1, Cartesian2.Cartesian3.ZERO)) {
  1502. i2 += 2;
  1503. continue;
  1504. }
  1505. encodeResult2 = AttributeCompression.AttributeCompression.octEncodeInRange(toEncode1, 65535, encodeResult2);
  1506. compressedDirections[i2++] = encodeResult2.x;
  1507. compressedDirections[i2++] = encodeResult2.y;
  1508. }
  1509. geometry.attributes.compressedAttributes = new GeometryAttribute.GeometryAttribute({
  1510. componentDatatype : ComponentDatatype.ComponentDatatype.FLOAT,
  1511. componentsPerAttribute : 2,
  1512. values : compressedDirections
  1513. });
  1514. delete geometry.attributes.extrudeDirection;
  1515. return geometry;
  1516. }
  1517. var normalAttribute = geometry.attributes.normal;
  1518. var stAttribute = geometry.attributes.st;
  1519. var hasNormal = defined.defined(normalAttribute);
  1520. var hasSt = defined.defined(stAttribute);
  1521. if (!hasNormal && !hasSt) {
  1522. return geometry;
  1523. }
  1524. var tangentAttribute = geometry.attributes.tangent;
  1525. var bitangentAttribute = geometry.attributes.bitangent;
  1526. var hasTangent = defined.defined(tangentAttribute);
  1527. var hasBitangent = defined.defined(bitangentAttribute);
  1528. var normals;
  1529. var st;
  1530. var tangents;
  1531. var bitangents;
  1532. if (hasNormal) {
  1533. normals = normalAttribute.values;
  1534. }
  1535. if (hasSt) {
  1536. st = stAttribute.values;
  1537. }
  1538. if (hasTangent) {
  1539. tangents = tangentAttribute.values;
  1540. }
  1541. if (hasBitangent) {
  1542. bitangents = bitangentAttribute.values;
  1543. }
  1544. var length = hasNormal ? normals.length : st.length;
  1545. var numComponents = hasNormal ? 3.0 : 2.0;
  1546. numVertices = length / numComponents;
  1547. var compressedLength = numVertices;
  1548. var numCompressedComponents = hasSt && hasNormal ? 2.0 : 1.0;
  1549. numCompressedComponents += hasTangent || hasBitangent ? 1.0 : 0.0;
  1550. compressedLength *= numCompressedComponents;
  1551. var compressedAttributes = new Float32Array(compressedLength);
  1552. var normalIndex = 0;
  1553. for (i = 0; i < numVertices; ++i) {
  1554. if (hasSt) {
  1555. Cartesian2.Cartesian2.fromArray(st, i * 2.0, scratchCartesian2$1);
  1556. compressedAttributes[normalIndex++] = AttributeCompression.AttributeCompression.compressTextureCoordinates(scratchCartesian2$1);
  1557. }
  1558. var index = i * 3.0;
  1559. if (hasNormal && defined.defined(tangents) && defined.defined(bitangents)) {
  1560. Cartesian2.Cartesian3.fromArray(normals, index, toEncode1);
  1561. Cartesian2.Cartesian3.fromArray(tangents, index, toEncode2);
  1562. Cartesian2.Cartesian3.fromArray(bitangents, index, toEncode3);
  1563. AttributeCompression.AttributeCompression.octPack(toEncode1, toEncode2, toEncode3, scratchCartesian2$1);
  1564. compressedAttributes[normalIndex++] = scratchCartesian2$1.x;
  1565. compressedAttributes[normalIndex++] = scratchCartesian2$1.y;
  1566. } else {
  1567. if (hasNormal) {
  1568. Cartesian2.Cartesian3.fromArray(normals, index, toEncode1);
  1569. compressedAttributes[normalIndex++] = AttributeCompression.AttributeCompression.octEncodeFloat(toEncode1);
  1570. }
  1571. if (hasTangent) {
  1572. Cartesian2.Cartesian3.fromArray(tangents, index, toEncode1);
  1573. compressedAttributes[normalIndex++] = AttributeCompression.AttributeCompression.octEncodeFloat(toEncode1);
  1574. }
  1575. if (hasBitangent) {
  1576. Cartesian2.Cartesian3.fromArray(bitangents, index, toEncode1);
  1577. compressedAttributes[normalIndex++] = AttributeCompression.AttributeCompression.octEncodeFloat(toEncode1);
  1578. }
  1579. }
  1580. }
  1581. geometry.attributes.compressedAttributes = new GeometryAttribute.GeometryAttribute({
  1582. componentDatatype : ComponentDatatype.ComponentDatatype.FLOAT,
  1583. componentsPerAttribute : numCompressedComponents,
  1584. values : compressedAttributes
  1585. });
  1586. if (hasNormal) {
  1587. delete geometry.attributes.normal;
  1588. }
  1589. if (hasSt) {
  1590. delete geometry.attributes.st;
  1591. }
  1592. if (hasBitangent) {
  1593. delete geometry.attributes.bitangent;
  1594. }
  1595. if (hasTangent) {
  1596. delete geometry.attributes.tangent;
  1597. }
  1598. return geometry;
  1599. };
  1600. function indexTriangles(geometry) {
  1601. if (defined.defined(geometry.indices)) {
  1602. return geometry;
  1603. }
  1604. var numberOfVertices = GeometryAttribute.Geometry.computeNumberOfVertices(geometry);
  1605. //>>includeStart('debug', pragmas.debug);
  1606. if (numberOfVertices < 3) {
  1607. throw new Check.DeveloperError('The number of vertices must be at least three.');
  1608. }
  1609. if (numberOfVertices % 3 !== 0) {
  1610. throw new Check.DeveloperError('The number of vertices must be a multiple of three.');
  1611. }
  1612. //>>includeEnd('debug');
  1613. var indices = IndexDatatype.IndexDatatype.createTypedArray(numberOfVertices, numberOfVertices);
  1614. for (var i = 0; i < numberOfVertices; ++i) {
  1615. indices[i] = i;
  1616. }
  1617. geometry.indices = indices;
  1618. return geometry;
  1619. }
  1620. function indexTriangleFan(geometry) {
  1621. var numberOfVertices = GeometryAttribute.Geometry.computeNumberOfVertices(geometry);
  1622. //>>includeStart('debug', pragmas.debug);
  1623. if (numberOfVertices < 3) {
  1624. throw new Check.DeveloperError('The number of vertices must be at least three.');
  1625. }
  1626. //>>includeEnd('debug');
  1627. var indices = IndexDatatype.IndexDatatype.createTypedArray(numberOfVertices, (numberOfVertices - 2) * 3);
  1628. indices[0] = 1;
  1629. indices[1] = 0;
  1630. indices[2] = 2;
  1631. var indicesIndex = 3;
  1632. for (var i = 3; i < numberOfVertices; ++i) {
  1633. indices[indicesIndex++] = i - 1;
  1634. indices[indicesIndex++] = 0;
  1635. indices[indicesIndex++] = i;
  1636. }
  1637. geometry.indices = indices;
  1638. geometry.primitiveType = GeometryAttribute.PrimitiveType.TRIANGLES;
  1639. return geometry;
  1640. }
  1641. function indexTriangleStrip(geometry) {
  1642. var numberOfVertices = GeometryAttribute.Geometry.computeNumberOfVertices(geometry);
  1643. //>>includeStart('debug', pragmas.debug);
  1644. if (numberOfVertices < 3) {
  1645. throw new Check.DeveloperError('The number of vertices must be at least 3.');
  1646. }
  1647. //>>includeEnd('debug');
  1648. var indices = IndexDatatype.IndexDatatype.createTypedArray(numberOfVertices, (numberOfVertices - 2) * 3);
  1649. indices[0] = 0;
  1650. indices[1] = 1;
  1651. indices[2] = 2;
  1652. if (numberOfVertices > 3) {
  1653. indices[3] = 0;
  1654. indices[4] = 2;
  1655. indices[5] = 3;
  1656. }
  1657. var indicesIndex = 6;
  1658. for (var i = 3; i < numberOfVertices - 1; i += 2) {
  1659. indices[indicesIndex++] = i;
  1660. indices[indicesIndex++] = i - 1;
  1661. indices[indicesIndex++] = i + 1;
  1662. if (i + 2 < numberOfVertices) {
  1663. indices[indicesIndex++] = i;
  1664. indices[indicesIndex++] = i + 1;
  1665. indices[indicesIndex++] = i + 2;
  1666. }
  1667. }
  1668. geometry.indices = indices;
  1669. geometry.primitiveType = GeometryAttribute.PrimitiveType.TRIANGLES;
  1670. return geometry;
  1671. }
  1672. function indexLines(geometry) {
  1673. if (defined.defined(geometry.indices)) {
  1674. return geometry;
  1675. }
  1676. var numberOfVertices = GeometryAttribute.Geometry.computeNumberOfVertices(geometry);
  1677. //>>includeStart('debug', pragmas.debug);
  1678. if (numberOfVertices < 2) {
  1679. throw new Check.DeveloperError('The number of vertices must be at least two.');
  1680. }
  1681. if (numberOfVertices % 2 !== 0) {
  1682. throw new Check.DeveloperError('The number of vertices must be a multiple of 2.');
  1683. }
  1684. //>>includeEnd('debug');
  1685. var indices = IndexDatatype.IndexDatatype.createTypedArray(numberOfVertices, numberOfVertices);
  1686. for (var i = 0; i < numberOfVertices; ++i) {
  1687. indices[i] = i;
  1688. }
  1689. geometry.indices = indices;
  1690. return geometry;
  1691. }
  1692. function indexLineStrip(geometry) {
  1693. var numberOfVertices = GeometryAttribute.Geometry.computeNumberOfVertices(geometry);
  1694. //>>includeStart('debug', pragmas.debug);
  1695. if (numberOfVertices < 2) {
  1696. throw new Check.DeveloperError('The number of vertices must be at least two.');
  1697. }
  1698. //>>includeEnd('debug');
  1699. var indices = IndexDatatype.IndexDatatype.createTypedArray(numberOfVertices, (numberOfVertices - 1) * 2);
  1700. indices[0] = 0;
  1701. indices[1] = 1;
  1702. var indicesIndex = 2;
  1703. for (var i = 2; i < numberOfVertices; ++i) {
  1704. indices[indicesIndex++] = i - 1;
  1705. indices[indicesIndex++] = i;
  1706. }
  1707. geometry.indices = indices;
  1708. geometry.primitiveType = GeometryAttribute.PrimitiveType.LINES;
  1709. return geometry;
  1710. }
  1711. function indexLineLoop(geometry) {
  1712. var numberOfVertices = GeometryAttribute.Geometry.computeNumberOfVertices(geometry);
  1713. //>>includeStart('debug', pragmas.debug);
  1714. if (numberOfVertices < 2) {
  1715. throw new Check.DeveloperError('The number of vertices must be at least two.');
  1716. }
  1717. //>>includeEnd('debug');
  1718. var indices = IndexDatatype.IndexDatatype.createTypedArray(numberOfVertices, numberOfVertices * 2);
  1719. indices[0] = 0;
  1720. indices[1] = 1;
  1721. var indicesIndex = 2;
  1722. for (var i = 2; i < numberOfVertices; ++i) {
  1723. indices[indicesIndex++] = i - 1;
  1724. indices[indicesIndex++] = i;
  1725. }
  1726. indices[indicesIndex++] = numberOfVertices - 1;
  1727. indices[indicesIndex] = 0;
  1728. geometry.indices = indices;
  1729. geometry.primitiveType = GeometryAttribute.PrimitiveType.LINES;
  1730. return geometry;
  1731. }
  1732. function indexPrimitive(geometry) {
  1733. switch (geometry.primitiveType) {
  1734. case GeometryAttribute.PrimitiveType.TRIANGLE_FAN:
  1735. return indexTriangleFan(geometry);
  1736. case GeometryAttribute.PrimitiveType.TRIANGLE_STRIP:
  1737. return indexTriangleStrip(geometry);
  1738. case GeometryAttribute.PrimitiveType.TRIANGLES:
  1739. return indexTriangles(geometry);
  1740. case GeometryAttribute.PrimitiveType.LINE_STRIP:
  1741. return indexLineStrip(geometry);
  1742. case GeometryAttribute.PrimitiveType.LINE_LOOP:
  1743. return indexLineLoop(geometry);
  1744. case GeometryAttribute.PrimitiveType.LINES:
  1745. return indexLines(geometry);
  1746. }
  1747. return geometry;
  1748. }
  1749. function offsetPointFromXZPlane(p, isBehind) {
  1750. if (Math.abs(p.y) < _Math.CesiumMath.EPSILON6){
  1751. if (isBehind) {
  1752. p.y = -_Math.CesiumMath.EPSILON6;
  1753. } else {
  1754. p.y = _Math.CesiumMath.EPSILON6;
  1755. }
  1756. }
  1757. }
  1758. function offsetTriangleFromXZPlane(p0, p1, p2) {
  1759. if (p0.y !== 0.0 && p1.y !== 0.0 && p2.y !== 0.0) {
  1760. offsetPointFromXZPlane(p0, p0.y < 0.0);
  1761. offsetPointFromXZPlane(p1, p1.y < 0.0);
  1762. offsetPointFromXZPlane(p2, p2.y < 0.0);
  1763. return;
  1764. }
  1765. var p0y = Math.abs(p0.y);
  1766. var p1y = Math.abs(p1.y);
  1767. var p2y = Math.abs(p2.y);
  1768. var sign;
  1769. if (p0y > p1y) {
  1770. if (p0y > p2y) {
  1771. sign = _Math.CesiumMath.sign(p0.y);
  1772. } else {
  1773. sign = _Math.CesiumMath.sign(p2.y);
  1774. }
  1775. } else if (p1y > p2y) {
  1776. sign = _Math.CesiumMath.sign(p1.y);
  1777. } else {
  1778. sign = _Math.CesiumMath.sign(p2.y);
  1779. }
  1780. var isBehind = sign < 0.0;
  1781. offsetPointFromXZPlane(p0, isBehind);
  1782. offsetPointFromXZPlane(p1, isBehind);
  1783. offsetPointFromXZPlane(p2, isBehind);
  1784. }
  1785. var c3 = new Cartesian2.Cartesian3();
  1786. function getXZIntersectionOffsetPoints(p, p1, u1, v1) {
  1787. Cartesian2.Cartesian3.add(p, Cartesian2.Cartesian3.multiplyByScalar(Cartesian2.Cartesian3.subtract(p1, p, c3), p.y/(p.y-p1.y), c3), u1);
  1788. Cartesian2.Cartesian3.clone(u1, v1);
  1789. offsetPointFromXZPlane(u1, true);
  1790. offsetPointFromXZPlane(v1, false);
  1791. }
  1792. var u1 = new Cartesian2.Cartesian3();
  1793. var u2 = new Cartesian2.Cartesian3();
  1794. var q1 = new Cartesian2.Cartesian3();
  1795. var q2 = new Cartesian2.Cartesian3();
  1796. var splitTriangleResult = {
  1797. positions : new Array(7),
  1798. indices : new Array(3 * 3)
  1799. };
  1800. function splitTriangle(p0, p1, p2) {
  1801. // In WGS84 coordinates, for a triangle approximately on the
  1802. // ellipsoid to cross the IDL, first it needs to be on the
  1803. // negative side of the plane x = 0.
  1804. if ((p0.x >= 0.0) || (p1.x >= 0.0) || (p2.x >= 0.0)) {
  1805. return undefined;
  1806. }
  1807. offsetTriangleFromXZPlane(p0, p1, p2);
  1808. var p0Behind = p0.y < 0.0;
  1809. var p1Behind = p1.y < 0.0;
  1810. var p2Behind = p2.y < 0.0;
  1811. var numBehind = 0;
  1812. numBehind += p0Behind ? 1 : 0;
  1813. numBehind += p1Behind ? 1 : 0;
  1814. numBehind += p2Behind ? 1 : 0;
  1815. var indices = splitTriangleResult.indices;
  1816. if (numBehind === 1) {
  1817. indices[1] = 3;
  1818. indices[2] = 4;
  1819. indices[5] = 6;
  1820. indices[7] = 6;
  1821. indices[8] = 5;
  1822. if (p0Behind) {
  1823. getXZIntersectionOffsetPoints(p0, p1, u1, q1);
  1824. getXZIntersectionOffsetPoints(p0, p2, u2, q2);
  1825. indices[0] = 0;
  1826. indices[3] = 1;
  1827. indices[4] = 2;
  1828. indices[6] = 1;
  1829. } else if (p1Behind) {
  1830. getXZIntersectionOffsetPoints(p1, p2, u1, q1);
  1831. getXZIntersectionOffsetPoints(p1, p0, u2, q2);
  1832. indices[0] = 1;
  1833. indices[3] = 2;
  1834. indices[4] = 0;
  1835. indices[6] = 2;
  1836. } else if (p2Behind) {
  1837. getXZIntersectionOffsetPoints(p2, p0, u1, q1);
  1838. getXZIntersectionOffsetPoints(p2, p1, u2, q2);
  1839. indices[0] = 2;
  1840. indices[3] = 0;
  1841. indices[4] = 1;
  1842. indices[6] = 0;
  1843. }
  1844. } else if (numBehind === 2) {
  1845. indices[2] = 4;
  1846. indices[4] = 4;
  1847. indices[5] = 3;
  1848. indices[7] = 5;
  1849. indices[8] = 6;
  1850. if (!p0Behind) {
  1851. getXZIntersectionOffsetPoints(p0, p1, u1, q1);
  1852. getXZIntersectionOffsetPoints(p0, p2, u2, q2);
  1853. indices[0] = 1;
  1854. indices[1] = 2;
  1855. indices[3] = 1;
  1856. indices[6] = 0;
  1857. } else if (!p1Behind) {
  1858. getXZIntersectionOffsetPoints(p1, p2, u1, q1);
  1859. getXZIntersectionOffsetPoints(p1, p0, u2, q2);
  1860. indices[0] = 2;
  1861. indices[1] = 0;
  1862. indices[3] = 2;
  1863. indices[6] = 1;
  1864. } else if (!p2Behind) {
  1865. getXZIntersectionOffsetPoints(p2, p0, u1, q1);
  1866. getXZIntersectionOffsetPoints(p2, p1, u2, q2);
  1867. indices[0] = 0;
  1868. indices[1] = 1;
  1869. indices[3] = 0;
  1870. indices[6] = 2;
  1871. }
  1872. }
  1873. var positions = splitTriangleResult.positions;
  1874. positions[0] = p0;
  1875. positions[1] = p1;
  1876. positions[2] = p2;
  1877. positions.length = 3;
  1878. if (numBehind === 1 || numBehind === 2) {
  1879. positions[3] = u1;
  1880. positions[4] = u2;
  1881. positions[5] = q1;
  1882. positions[6] = q2;
  1883. positions.length = 7;
  1884. }
  1885. return splitTriangleResult;
  1886. }
  1887. function updateGeometryAfterSplit(geometry, computeBoundingSphere) {
  1888. var attributes = geometry.attributes;
  1889. if (attributes.position.values.length === 0) {
  1890. return undefined;
  1891. }
  1892. for (var property in attributes) {
  1893. if (attributes.hasOwnProperty(property) &&
  1894. defined.defined(attributes[property]) &&
  1895. defined.defined(attributes[property].values)) {
  1896. var attribute = attributes[property];
  1897. attribute.values = ComponentDatatype.ComponentDatatype.createTypedArray(attribute.componentDatatype, attribute.values);
  1898. }
  1899. }
  1900. var numberOfVertices = GeometryAttribute.Geometry.computeNumberOfVertices(geometry);
  1901. geometry.indices = IndexDatatype.IndexDatatype.createTypedArray(numberOfVertices, geometry.indices);
  1902. if (computeBoundingSphere) {
  1903. geometry.boundingSphere = Transforms.BoundingSphere.fromVertices(attributes.position.values);
  1904. }
  1905. return geometry;
  1906. }
  1907. function copyGeometryForSplit(geometry) {
  1908. var attributes = geometry.attributes;
  1909. var copiedAttributes = {};
  1910. for (var property in attributes) {
  1911. if (attributes.hasOwnProperty(property) &&
  1912. defined.defined(attributes[property]) &&
  1913. defined.defined(attributes[property].values)) {
  1914. var attribute = attributes[property];
  1915. copiedAttributes[property] = new GeometryAttribute.GeometryAttribute({
  1916. componentDatatype : attribute.componentDatatype,
  1917. componentsPerAttribute : attribute.componentsPerAttribute,
  1918. normalize : attribute.normalize,
  1919. values : []
  1920. });
  1921. }
  1922. }
  1923. return new GeometryAttribute.Geometry({
  1924. attributes : copiedAttributes,
  1925. indices : [],
  1926. primitiveType : geometry.primitiveType
  1927. });
  1928. }
  1929. function updateInstanceAfterSplit(instance, westGeometry, eastGeometry) {
  1930. var computeBoundingSphere = defined.defined(instance.geometry.boundingSphere);
  1931. westGeometry = updateGeometryAfterSplit(westGeometry, computeBoundingSphere);
  1932. eastGeometry = updateGeometryAfterSplit(eastGeometry, computeBoundingSphere);
  1933. if (defined.defined(eastGeometry) && !defined.defined(westGeometry)) {
  1934. instance.geometry = eastGeometry;
  1935. } else if (!defined.defined(eastGeometry) && defined.defined(westGeometry)) {
  1936. instance.geometry = westGeometry;
  1937. } else {
  1938. instance.westHemisphereGeometry = westGeometry;
  1939. instance.eastHemisphereGeometry = eastGeometry;
  1940. instance.geometry = undefined;
  1941. }
  1942. }
  1943. function generateBarycentricInterpolateFunction(CartesianType, numberOfComponents) {
  1944. var v0Scratch = new CartesianType();
  1945. var v1Scratch = new CartesianType();
  1946. var v2Scratch = new CartesianType();
  1947. return function(i0, i1, i2, coords, sourceValues, currentValues, insertedIndex, normalize) {
  1948. var v0 = CartesianType.fromArray(sourceValues, i0 * numberOfComponents, v0Scratch);
  1949. var v1 = CartesianType.fromArray(sourceValues, i1 * numberOfComponents, v1Scratch);
  1950. var v2 = CartesianType.fromArray(sourceValues, i2 * numberOfComponents, v2Scratch);
  1951. CartesianType.multiplyByScalar(v0, coords.x, v0);
  1952. CartesianType.multiplyByScalar(v1, coords.y, v1);
  1953. CartesianType.multiplyByScalar(v2, coords.z, v2);
  1954. var value = CartesianType.add(v0, v1, v0);
  1955. CartesianType.add(value, v2, value);
  1956. if (normalize) {
  1957. CartesianType.normalize(value, value);
  1958. }
  1959. CartesianType.pack(value, currentValues, insertedIndex * numberOfComponents);
  1960. };
  1961. }
  1962. var interpolateAndPackCartesian4 = generateBarycentricInterpolateFunction(Transforms.Cartesian4, 4);
  1963. var interpolateAndPackCartesian3 = generateBarycentricInterpolateFunction(Cartesian2.Cartesian3, 3);
  1964. var interpolateAndPackCartesian2 = generateBarycentricInterpolateFunction(Cartesian2.Cartesian2, 2);
  1965. var interpolateAndPackBoolean = function(i0, i1, i2, coords, sourceValues, currentValues, insertedIndex) {
  1966. var v1 = sourceValues[i0] * coords.x;
  1967. var v2 = sourceValues[i1] * coords.y;
  1968. var v3 = sourceValues[i2] * coords.z;
  1969. currentValues[insertedIndex] = (v1 + v2 + v3) > _Math.CesiumMath.EPSILON6 ? 1 : 0;
  1970. };
  1971. var p0Scratch = new Cartesian2.Cartesian3();
  1972. var p1Scratch = new Cartesian2.Cartesian3();
  1973. var p2Scratch = new Cartesian2.Cartesian3();
  1974. var barycentricScratch = new Cartesian2.Cartesian3();
  1975. function computeTriangleAttributes(i0, i1, i2, point, positions, normals, tangents, bitangents, texCoords, extrudeDirections, applyOffset, currentAttributes, customAttributeNames, customAttributesLength, allAttributes, insertedIndex) {
  1976. if (!defined.defined(normals) && !defined.defined(tangents) && !defined.defined(bitangents) && !defined.defined(texCoords) && !defined.defined(extrudeDirections) && customAttributesLength === 0) {
  1977. return;
  1978. }
  1979. var p0 = Cartesian2.Cartesian3.fromArray(positions, i0 * 3, p0Scratch);
  1980. var p1 = Cartesian2.Cartesian3.fromArray(positions, i1 * 3, p1Scratch);
  1981. var p2 = Cartesian2.Cartesian3.fromArray(positions, i2 * 3, p2Scratch);
  1982. var coords = barycentricCoordinates(point, p0, p1, p2, barycentricScratch);
  1983. if (defined.defined(normals)) {
  1984. interpolateAndPackCartesian3(i0, i1, i2, coords, normals, currentAttributes.normal.values, insertedIndex, true);
  1985. }
  1986. if (defined.defined(extrudeDirections)) {
  1987. var d0 = Cartesian2.Cartesian3.fromArray(extrudeDirections, i0 * 3, p0Scratch);
  1988. var d1 = Cartesian2.Cartesian3.fromArray(extrudeDirections, i1 * 3, p1Scratch);
  1989. var d2 = Cartesian2.Cartesian3.fromArray(extrudeDirections, i2 * 3, p2Scratch);
  1990. Cartesian2.Cartesian3.multiplyByScalar(d0, coords.x, d0);
  1991. Cartesian2.Cartesian3.multiplyByScalar(d1, coords.y, d1);
  1992. Cartesian2.Cartesian3.multiplyByScalar(d2, coords.z, d2);
  1993. var direction;
  1994. if (!Cartesian2.Cartesian3.equals(d0, Cartesian2.Cartesian3.ZERO) || !Cartesian2.Cartesian3.equals(d1, Cartesian2.Cartesian3.ZERO) || !Cartesian2.Cartesian3.equals(d2, Cartesian2.Cartesian3.ZERO)) {
  1995. direction = Cartesian2.Cartesian3.add(d0, d1, d0);
  1996. Cartesian2.Cartesian3.add(direction, d2, direction);
  1997. Cartesian2.Cartesian3.normalize(direction, direction);
  1998. } else {
  1999. direction = p0Scratch;
  2000. direction.x = 0;
  2001. direction.y = 0;
  2002. direction.z = 0;
  2003. }
  2004. Cartesian2.Cartesian3.pack(direction, currentAttributes.extrudeDirection.values, insertedIndex * 3);
  2005. }
  2006. if (defined.defined(applyOffset)) {
  2007. interpolateAndPackBoolean(i0, i1, i2, coords, applyOffset, currentAttributes.applyOffset.values, insertedIndex);
  2008. }
  2009. if (defined.defined(tangents)) {
  2010. interpolateAndPackCartesian3(i0, i1, i2, coords, tangents, currentAttributes.tangent.values, insertedIndex, true);
  2011. }
  2012. if (defined.defined(bitangents)) {
  2013. interpolateAndPackCartesian3(i0, i1, i2, coords, bitangents, currentAttributes.bitangent.values, insertedIndex, true);
  2014. }
  2015. if (defined.defined(texCoords)) {
  2016. interpolateAndPackCartesian2(i0, i1, i2, coords, texCoords, currentAttributes.st.values, insertedIndex);
  2017. }
  2018. if (customAttributesLength > 0) {
  2019. for (var i = 0; i < customAttributesLength; i++) {
  2020. var attributeName = customAttributeNames[i];
  2021. genericInterpolate(i0, i1, i2, coords, insertedIndex, allAttributes[attributeName], currentAttributes[attributeName]);
  2022. }
  2023. }
  2024. }
  2025. function genericInterpolate(i0, i1, i2, coords, insertedIndex, sourceAttribute, currentAttribute) {
  2026. var componentsPerAttribute = sourceAttribute.componentsPerAttribute;
  2027. var sourceValues = sourceAttribute.values;
  2028. var currentValues = currentAttribute.values;
  2029. switch(componentsPerAttribute) {
  2030. case 4:
  2031. interpolateAndPackCartesian4(i0, i1, i2, coords, sourceValues, currentValues, insertedIndex, false);
  2032. break;
  2033. case 3:
  2034. interpolateAndPackCartesian3(i0, i1, i2, coords, sourceValues, currentValues, insertedIndex, false);
  2035. break;
  2036. case 2:
  2037. interpolateAndPackCartesian2(i0, i1, i2, coords, sourceValues, currentValues, insertedIndex, false);
  2038. break;
  2039. default:
  2040. currentValues[insertedIndex] = sourceValues[i0] * coords.x + sourceValues[i1] * coords.y + sourceValues[i2] * coords.z;
  2041. }
  2042. }
  2043. function insertSplitPoint(currentAttributes, currentIndices, currentIndexMap, indices, currentIndex, point) {
  2044. var insertIndex = currentAttributes.position.values.length / 3;
  2045. if (currentIndex !== -1) {
  2046. var prevIndex = indices[currentIndex];
  2047. var newIndex = currentIndexMap[prevIndex];
  2048. if (newIndex === -1) {
  2049. currentIndexMap[prevIndex] = insertIndex;
  2050. currentAttributes.position.values.push(point.x, point.y, point.z);
  2051. currentIndices.push(insertIndex);
  2052. return insertIndex;
  2053. }
  2054. currentIndices.push(newIndex);
  2055. return newIndex;
  2056. }
  2057. currentAttributes.position.values.push(point.x, point.y, point.z);
  2058. currentIndices.push(insertIndex);
  2059. return insertIndex;
  2060. }
  2061. var NAMED_ATTRIBUTES = {
  2062. position : true,
  2063. normal : true,
  2064. bitangent : true,
  2065. tangent : true,
  2066. st : true,
  2067. extrudeDirection : true,
  2068. applyOffset: true
  2069. };
  2070. function splitLongitudeTriangles(instance) {
  2071. var geometry = instance.geometry;
  2072. var attributes = geometry.attributes;
  2073. var positions = attributes.position.values;
  2074. var normals = (defined.defined(attributes.normal)) ? attributes.normal.values : undefined;
  2075. var bitangents = (defined.defined(attributes.bitangent)) ? attributes.bitangent.values : undefined;
  2076. var tangents = (defined.defined(attributes.tangent)) ? attributes.tangent.values : undefined;
  2077. var texCoords = (defined.defined(attributes.st)) ? attributes.st.values : undefined;
  2078. var extrudeDirections = (defined.defined(attributes.extrudeDirection)) ? attributes.extrudeDirection.values : undefined;
  2079. var applyOffset = defined.defined(attributes.applyOffset) ? attributes.applyOffset.values : undefined;
  2080. var indices = geometry.indices;
  2081. var customAttributeNames = [];
  2082. for (var attributeName in attributes) {
  2083. if (attributes.hasOwnProperty(attributeName) && !NAMED_ATTRIBUTES[attributeName] && defined.defined(attributes[attributeName])) {
  2084. customAttributeNames.push(attributeName);
  2085. }
  2086. }
  2087. var customAttributesLength = customAttributeNames.length;
  2088. var eastGeometry = copyGeometryForSplit(geometry);
  2089. var westGeometry = copyGeometryForSplit(geometry);
  2090. var currentAttributes;
  2091. var currentIndices;
  2092. var currentIndexMap;
  2093. var insertedIndex;
  2094. var i;
  2095. var westGeometryIndexMap = [];
  2096. westGeometryIndexMap.length = positions.length / 3;
  2097. var eastGeometryIndexMap = [];
  2098. eastGeometryIndexMap.length = positions.length / 3;
  2099. for (i = 0; i < westGeometryIndexMap.length; ++i) {
  2100. westGeometryIndexMap[i] = -1;
  2101. eastGeometryIndexMap[i] = -1;
  2102. }
  2103. var len = indices.length;
  2104. for (i = 0; i < len; i += 3) {
  2105. var i0 = indices[i];
  2106. var i1 = indices[i + 1];
  2107. var i2 = indices[i + 2];
  2108. var p0 = Cartesian2.Cartesian3.fromArray(positions, i0 * 3);
  2109. var p1 = Cartesian2.Cartesian3.fromArray(positions, i1 * 3);
  2110. var p2 = Cartesian2.Cartesian3.fromArray(positions, i2 * 3);
  2111. var result = splitTriangle(p0, p1, p2);
  2112. if (defined.defined(result) && result.positions.length > 3) {
  2113. var resultPositions = result.positions;
  2114. var resultIndices = result.indices;
  2115. var resultLength = resultIndices.length;
  2116. for (var j = 0; j < resultLength; ++j) {
  2117. var resultIndex = resultIndices[j];
  2118. var point = resultPositions[resultIndex];
  2119. if (point.y < 0.0) {
  2120. currentAttributes = westGeometry.attributes;
  2121. currentIndices = westGeometry.indices;
  2122. currentIndexMap = westGeometryIndexMap;
  2123. } else {
  2124. currentAttributes = eastGeometry.attributes;
  2125. currentIndices = eastGeometry.indices;
  2126. currentIndexMap = eastGeometryIndexMap;
  2127. }
  2128. insertedIndex = insertSplitPoint(currentAttributes, currentIndices, currentIndexMap, indices, resultIndex < 3 ? i + resultIndex : -1, point);
  2129. computeTriangleAttributes(i0, i1, i2, point, positions, normals, tangents, bitangents, texCoords, extrudeDirections, applyOffset, currentAttributes, customAttributeNames, customAttributesLength, attributes, insertedIndex);
  2130. }
  2131. } else {
  2132. if (defined.defined(result)) {
  2133. p0 = result.positions[0];
  2134. p1 = result.positions[1];
  2135. p2 = result.positions[2];
  2136. }
  2137. if (p0.y < 0.0) {
  2138. currentAttributes = westGeometry.attributes;
  2139. currentIndices = westGeometry.indices;
  2140. currentIndexMap = westGeometryIndexMap;
  2141. } else {
  2142. currentAttributes = eastGeometry.attributes;
  2143. currentIndices = eastGeometry.indices;
  2144. currentIndexMap = eastGeometryIndexMap;
  2145. }
  2146. insertedIndex = insertSplitPoint(currentAttributes, currentIndices, currentIndexMap, indices, i, p0);
  2147. computeTriangleAttributes(i0, i1, i2, p0, positions, normals, tangents, bitangents, texCoords, extrudeDirections, applyOffset, currentAttributes, customAttributeNames, customAttributesLength, attributes, insertedIndex);
  2148. insertedIndex = insertSplitPoint(currentAttributes, currentIndices, currentIndexMap, indices, i + 1, p1);
  2149. computeTriangleAttributes(i0, i1, i2, p1, positions, normals, tangents, bitangents, texCoords, extrudeDirections, applyOffset, currentAttributes, customAttributeNames, customAttributesLength, attributes, insertedIndex);
  2150. insertedIndex = insertSplitPoint(currentAttributes, currentIndices, currentIndexMap, indices, i + 2, p2);
  2151. computeTriangleAttributes(i0, i1, i2, p2, positions, normals, tangents, bitangents, texCoords, extrudeDirections, applyOffset, currentAttributes, customAttributeNames, customAttributesLength, attributes, insertedIndex);
  2152. }
  2153. }
  2154. updateInstanceAfterSplit(instance, westGeometry, eastGeometry);
  2155. }
  2156. var xzPlane = Plane.Plane.fromPointNormal(Cartesian2.Cartesian3.ZERO, Cartesian2.Cartesian3.UNIT_Y);
  2157. var offsetScratch = new Cartesian2.Cartesian3();
  2158. var offsetPointScratch = new Cartesian2.Cartesian3();
  2159. function computeLineAttributes(i0, i1, point, positions, insertIndex, currentAttributes, applyOffset) {
  2160. if (!defined.defined(applyOffset)) {
  2161. return;
  2162. }
  2163. var p0 = Cartesian2.Cartesian3.fromArray(positions, i0 * 3, p0Scratch);
  2164. if (Cartesian2.Cartesian3.equalsEpsilon(p0, point, _Math.CesiumMath.EPSILON10)) {
  2165. currentAttributes.applyOffset.values[insertIndex] = applyOffset[i0];
  2166. } else {
  2167. currentAttributes.applyOffset.values[insertIndex] = applyOffset[i1];
  2168. }
  2169. }
  2170. function splitLongitudeLines(instance) {
  2171. var geometry = instance.geometry;
  2172. var attributes = geometry.attributes;
  2173. var positions = attributes.position.values;
  2174. var applyOffset = defined.defined(attributes.applyOffset) ? attributes.applyOffset.values : undefined;
  2175. var indices = geometry.indices;
  2176. var eastGeometry = copyGeometryForSplit(geometry);
  2177. var westGeometry = copyGeometryForSplit(geometry);
  2178. var i;
  2179. var length = indices.length;
  2180. var westGeometryIndexMap = [];
  2181. westGeometryIndexMap.length = positions.length / 3;
  2182. var eastGeometryIndexMap = [];
  2183. eastGeometryIndexMap.length = positions.length / 3;
  2184. for (i = 0; i < westGeometryIndexMap.length; ++i) {
  2185. westGeometryIndexMap[i] = -1;
  2186. eastGeometryIndexMap[i] = -1;
  2187. }
  2188. for (i = 0; i < length; i += 2) {
  2189. var i0 = indices[i];
  2190. var i1 = indices[i + 1];
  2191. var p0 = Cartesian2.Cartesian3.fromArray(positions, i0 * 3, p0Scratch);
  2192. var p1 = Cartesian2.Cartesian3.fromArray(positions, i1 * 3, p1Scratch);
  2193. var insertIndex;
  2194. if (Math.abs(p0.y) < _Math.CesiumMath.EPSILON6){
  2195. if (p0.y < 0.0) {
  2196. p0.y = -_Math.CesiumMath.EPSILON6;
  2197. } else {
  2198. p0.y = _Math.CesiumMath.EPSILON6;
  2199. }
  2200. }
  2201. if (Math.abs(p1.y) < _Math.CesiumMath.EPSILON6){
  2202. if (p1.y < 0.0) {
  2203. p1.y = -_Math.CesiumMath.EPSILON6;
  2204. } else {
  2205. p1.y = _Math.CesiumMath.EPSILON6;
  2206. }
  2207. }
  2208. var p0Attributes = eastGeometry.attributes;
  2209. var p0Indices = eastGeometry.indices;
  2210. var p0IndexMap = eastGeometryIndexMap;
  2211. var p1Attributes = westGeometry.attributes;
  2212. var p1Indices = westGeometry.indices;
  2213. var p1IndexMap = westGeometryIndexMap;
  2214. var intersection = IntersectionTests.IntersectionTests.lineSegmentPlane(p0, p1, xzPlane, p2Scratch);
  2215. if (defined.defined(intersection)) {
  2216. // move point on the xz-plane slightly away from the plane
  2217. var offset = Cartesian2.Cartesian3.multiplyByScalar(Cartesian2.Cartesian3.UNIT_Y, 5.0 * _Math.CesiumMath.EPSILON9, offsetScratch);
  2218. if (p0.y < 0.0) {
  2219. Cartesian2.Cartesian3.negate(offset, offset);
  2220. p0Attributes = westGeometry.attributes;
  2221. p0Indices = westGeometry.indices;
  2222. p0IndexMap = westGeometryIndexMap;
  2223. p1Attributes = eastGeometry.attributes;
  2224. p1Indices = eastGeometry.indices;
  2225. p1IndexMap = eastGeometryIndexMap;
  2226. }
  2227. var offsetPoint = Cartesian2.Cartesian3.add(intersection, offset, offsetPointScratch);
  2228. insertIndex = insertSplitPoint(p0Attributes, p0Indices, p0IndexMap, indices, i, p0);
  2229. computeLineAttributes(i0, i1, p0, positions, insertIndex, p0Attributes, applyOffset);
  2230. insertIndex = insertSplitPoint(p0Attributes, p0Indices, p0IndexMap, indices, -1, offsetPoint);
  2231. computeLineAttributes(i0, i1, offsetPoint, positions, insertIndex, p0Attributes, applyOffset);
  2232. Cartesian2.Cartesian3.negate(offset, offset);
  2233. Cartesian2.Cartesian3.add(intersection, offset, offsetPoint);
  2234. insertIndex = insertSplitPoint(p1Attributes, p1Indices, p1IndexMap, indices, -1, offsetPoint);
  2235. computeLineAttributes(i0, i1, offsetPoint, positions, insertIndex, p1Attributes, applyOffset);
  2236. insertIndex = insertSplitPoint(p1Attributes, p1Indices, p1IndexMap, indices, i + 1, p1);
  2237. computeLineAttributes(i0, i1, p1, positions, insertIndex, p1Attributes, applyOffset);
  2238. } else {
  2239. var currentAttributes;
  2240. var currentIndices;
  2241. var currentIndexMap;
  2242. if (p0.y < 0.0) {
  2243. currentAttributes = westGeometry.attributes;
  2244. currentIndices = westGeometry.indices;
  2245. currentIndexMap = westGeometryIndexMap;
  2246. } else {
  2247. currentAttributes = eastGeometry.attributes;
  2248. currentIndices = eastGeometry.indices;
  2249. currentIndexMap = eastGeometryIndexMap;
  2250. }
  2251. insertIndex = insertSplitPoint(currentAttributes, currentIndices, currentIndexMap, indices, i, p0);
  2252. computeLineAttributes(i0, i1, p0, positions, insertIndex, currentAttributes, applyOffset);
  2253. insertIndex = insertSplitPoint(currentAttributes, currentIndices, currentIndexMap, indices, i + 1, p1);
  2254. computeLineAttributes(i0, i1, p1, positions, insertIndex, currentAttributes, applyOffset);
  2255. }
  2256. }
  2257. updateInstanceAfterSplit(instance, westGeometry, eastGeometry);
  2258. }
  2259. var cartesian2Scratch0 = new Cartesian2.Cartesian2();
  2260. var cartesian2Scratch1 = new Cartesian2.Cartesian2();
  2261. var cartesian3Scratch0 = new Cartesian2.Cartesian3();
  2262. var cartesian3Scratch2 = new Cartesian2.Cartesian3();
  2263. var cartesian3Scratch3 = new Cartesian2.Cartesian3();
  2264. var cartesian3Scratch4 = new Cartesian2.Cartesian3();
  2265. var cartesian3Scratch5 = new Cartesian2.Cartesian3();
  2266. var cartesian3Scratch6 = new Cartesian2.Cartesian3();
  2267. var cartesian4Scratch0 = new Transforms.Cartesian4();
  2268. function updateAdjacencyAfterSplit(geometry) {
  2269. var attributes = geometry.attributes;
  2270. var positions = attributes.position.values;
  2271. var prevPositions = attributes.prevPosition.values;
  2272. var nextPositions = attributes.nextPosition.values;
  2273. var length = positions.length;
  2274. for (var j = 0; j < length; j += 3) {
  2275. var position = Cartesian2.Cartesian3.unpack(positions, j, cartesian3Scratch0);
  2276. if (position.x > 0.0) {
  2277. continue;
  2278. }
  2279. var prevPosition = Cartesian2.Cartesian3.unpack(prevPositions, j, cartesian3Scratch2);
  2280. if ((position.y < 0.0 && prevPosition.y > 0.0) || (position.y > 0.0 && prevPosition.y < 0.0)) {
  2281. if (j - 3 > 0) {
  2282. prevPositions[j] = positions[j - 3];
  2283. prevPositions[j + 1] = positions[j - 2];
  2284. prevPositions[j + 2] = positions[j - 1];
  2285. } else {
  2286. Cartesian2.Cartesian3.pack(position, prevPositions, j);
  2287. }
  2288. }
  2289. var nextPosition = Cartesian2.Cartesian3.unpack(nextPositions, j, cartesian3Scratch3);
  2290. if ((position.y < 0.0 && nextPosition.y > 0.0) || (position.y > 0.0 && nextPosition.y < 0.0)) {
  2291. if (j + 3 < length) {
  2292. nextPositions[j] = positions[j + 3];
  2293. nextPositions[j + 1] = positions[j + 4];
  2294. nextPositions[j + 2] = positions[j + 5];
  2295. } else {
  2296. Cartesian2.Cartesian3.pack(position, nextPositions, j);
  2297. }
  2298. }
  2299. }
  2300. }
  2301. var offsetScalar = 5.0 * _Math.CesiumMath.EPSILON9;
  2302. var coplanarOffset = _Math.CesiumMath.EPSILON6;
  2303. function splitLongitudePolyline(instance) {
  2304. var geometry = instance.geometry;
  2305. var attributes = geometry.attributes;
  2306. var positions = attributes.position.values;
  2307. var prevPositions = attributes.prevPosition.values;
  2308. var nextPositions = attributes.nextPosition.values;
  2309. var expandAndWidths = attributes.expandAndWidth.values;
  2310. var texCoords = (defined.defined(attributes.st)) ? attributes.st.values : undefined;
  2311. var colors = (defined.defined(attributes.color)) ? attributes.color.values : undefined;
  2312. var eastGeometry = copyGeometryForSplit(geometry);
  2313. var westGeometry = copyGeometryForSplit(geometry);
  2314. var i;
  2315. var j;
  2316. var index;
  2317. var intersectionFound = false;
  2318. var length = positions.length / 3;
  2319. for (i = 0; i < length; i += 4) {
  2320. var i0 = i;
  2321. var i2 = i + 2;
  2322. var p0 = Cartesian2.Cartesian3.fromArray(positions, i0 * 3, cartesian3Scratch0);
  2323. var p2 = Cartesian2.Cartesian3.fromArray(positions, i2 * 3, cartesian3Scratch2);
  2324. // Offset points that are close to the 180 longitude and change the previous/next point
  2325. // to be the same offset point so it can be projected to 2D. There is special handling in the
  2326. // shader for when position == prevPosition || position == nextPosition.
  2327. if (Math.abs(p0.y) < coplanarOffset) {
  2328. p0.y = coplanarOffset * (p2.y < 0.0 ? -1.0 : 1.0);
  2329. positions[i * 3 + 1] = p0.y;
  2330. positions[(i + 1) * 3 + 1] = p0.y;
  2331. for (j = i0 * 3; j < i0 * 3 + 4 * 3; j += 3) {
  2332. prevPositions[j] = positions[i * 3];
  2333. prevPositions[j + 1] = positions[i * 3 + 1];
  2334. prevPositions[j + 2] = positions[i * 3 + 2];
  2335. }
  2336. }
  2337. // Do the same but for when the line crosses 180 longitude in the opposite direction.
  2338. if (Math.abs(p2.y) < coplanarOffset) {
  2339. p2.y = coplanarOffset * (p0.y < 0.0 ? -1.0 : 1.0);
  2340. positions[(i + 2) * 3 + 1] = p2.y;
  2341. positions[(i + 3) * 3 + 1] = p2.y;
  2342. for (j = i0 * 3; j < i0 * 3 + 4 * 3; j += 3) {
  2343. nextPositions[j] = positions[(i + 2) * 3];
  2344. nextPositions[j + 1] = positions[(i + 2) * 3 + 1];
  2345. nextPositions[j + 2] = positions[(i + 2) * 3 + 2];
  2346. }
  2347. }
  2348. var p0Attributes = eastGeometry.attributes;
  2349. var p0Indices = eastGeometry.indices;
  2350. var p2Attributes = westGeometry.attributes;
  2351. var p2Indices = westGeometry.indices;
  2352. var intersection = IntersectionTests.IntersectionTests.lineSegmentPlane(p0, p2, xzPlane, cartesian3Scratch4);
  2353. if (defined.defined(intersection)) {
  2354. intersectionFound = true;
  2355. // move point on the xz-plane slightly away from the plane
  2356. var offset = Cartesian2.Cartesian3.multiplyByScalar(Cartesian2.Cartesian3.UNIT_Y, offsetScalar, cartesian3Scratch5);
  2357. if (p0.y < 0.0) {
  2358. Cartesian2.Cartesian3.negate(offset, offset);
  2359. p0Attributes = westGeometry.attributes;
  2360. p0Indices = westGeometry.indices;
  2361. p2Attributes = eastGeometry.attributes;
  2362. p2Indices = eastGeometry.indices;
  2363. }
  2364. var offsetPoint = Cartesian2.Cartesian3.add(intersection, offset, cartesian3Scratch6);
  2365. p0Attributes.position.values.push(p0.x, p0.y, p0.z, p0.x, p0.y, p0.z);
  2366. p0Attributes.position.values.push(offsetPoint.x, offsetPoint.y, offsetPoint.z);
  2367. p0Attributes.position.values.push(offsetPoint.x, offsetPoint.y, offsetPoint.z);
  2368. p0Attributes.prevPosition.values.push(prevPositions[i0 * 3], prevPositions[i0 * 3 + 1], prevPositions[i0 * 3 + 2]);
  2369. p0Attributes.prevPosition.values.push(prevPositions[i0 * 3 + 3], prevPositions[i0 * 3 + 4], prevPositions[i0 * 3 + 5]);
  2370. p0Attributes.prevPosition.values.push(p0.x, p0.y, p0.z, p0.x, p0.y, p0.z);
  2371. p0Attributes.nextPosition.values.push(offsetPoint.x, offsetPoint.y, offsetPoint.z);
  2372. p0Attributes.nextPosition.values.push(offsetPoint.x, offsetPoint.y, offsetPoint.z);
  2373. p0Attributes.nextPosition.values.push(offsetPoint.x, offsetPoint.y, offsetPoint.z);
  2374. p0Attributes.nextPosition.values.push(offsetPoint.x, offsetPoint.y, offsetPoint.z);
  2375. Cartesian2.Cartesian3.negate(offset, offset);
  2376. Cartesian2.Cartesian3.add(intersection, offset, offsetPoint);
  2377. p2Attributes.position.values.push(offsetPoint.x, offsetPoint.y, offsetPoint.z);
  2378. p2Attributes.position.values.push(offsetPoint.x, offsetPoint.y, offsetPoint.z);
  2379. p2Attributes.position.values.push(p2.x, p2.y, p2.z, p2.x, p2.y, p2.z);
  2380. p2Attributes.prevPosition.values.push(offsetPoint.x, offsetPoint.y, offsetPoint.z);
  2381. p2Attributes.prevPosition.values.push(offsetPoint.x, offsetPoint.y, offsetPoint.z);
  2382. p2Attributes.prevPosition.values.push(offsetPoint.x, offsetPoint.y, offsetPoint.z);
  2383. p2Attributes.prevPosition.values.push(offsetPoint.x, offsetPoint.y, offsetPoint.z);
  2384. p2Attributes.nextPosition.values.push(p2.x, p2.y, p2.z, p2.x, p2.y, p2.z);
  2385. p2Attributes.nextPosition.values.push(nextPositions[i2 * 3], nextPositions[i2 * 3 + 1], nextPositions[i2 * 3 + 2]);
  2386. p2Attributes.nextPosition.values.push(nextPositions[i2 * 3 + 3], nextPositions[i2 * 3 + 4], nextPositions[i2 * 3 + 5]);
  2387. var ew0 = Cartesian2.Cartesian2.fromArray(expandAndWidths, i0 * 2, cartesian2Scratch0);
  2388. var width = Math.abs(ew0.y);
  2389. p0Attributes.expandAndWidth.values.push(-1, width, 1, width);
  2390. p0Attributes.expandAndWidth.values.push(-1, -width, 1, -width);
  2391. p2Attributes.expandAndWidth.values.push(-1, width, 1, width);
  2392. p2Attributes.expandAndWidth.values.push(-1, -width, 1, -width);
  2393. var t = Cartesian2.Cartesian3.magnitudeSquared(Cartesian2.Cartesian3.subtract(intersection, p0, cartesian3Scratch3));
  2394. t /= Cartesian2.Cartesian3.magnitudeSquared(Cartesian2.Cartesian3.subtract(p2, p0, cartesian3Scratch3));
  2395. if (defined.defined(colors)) {
  2396. var c0 = Transforms.Cartesian4.fromArray(colors, i0 * 4, cartesian4Scratch0);
  2397. var c2 = Transforms.Cartesian4.fromArray(colors, i2 * 4, cartesian4Scratch0);
  2398. var r = _Math.CesiumMath.lerp(c0.x, c2.x, t);
  2399. var g = _Math.CesiumMath.lerp(c0.y, c2.y, t);
  2400. var b = _Math.CesiumMath.lerp(c0.z, c2.z, t);
  2401. var a = _Math.CesiumMath.lerp(c0.w, c2.w, t);
  2402. for (j = i0 * 4; j < i0 * 4 + 2 * 4; ++j) {
  2403. p0Attributes.color.values.push(colors[j]);
  2404. }
  2405. p0Attributes.color.values.push(r, g, b, a);
  2406. p0Attributes.color.values.push(r, g, b, a);
  2407. p2Attributes.color.values.push(r, g, b, a);
  2408. p2Attributes.color.values.push(r, g, b, a);
  2409. for (j = i2 * 4; j < i2 * 4 + 2 * 4; ++j) {
  2410. p2Attributes.color.values.push(colors[j]);
  2411. }
  2412. }
  2413. if (defined.defined(texCoords)) {
  2414. var s0 = Cartesian2.Cartesian2.fromArray(texCoords, i0 * 2, cartesian2Scratch0);
  2415. var s3 = Cartesian2.Cartesian2.fromArray(texCoords, (i + 3) * 2, cartesian2Scratch1);
  2416. var sx = _Math.CesiumMath.lerp(s0.x, s3.x, t);
  2417. for (j = i0 * 2; j < i0 * 2 + 2 * 2; ++j) {
  2418. p0Attributes.st.values.push(texCoords[j]);
  2419. }
  2420. p0Attributes.st.values.push(sx, s0.y);
  2421. p0Attributes.st.values.push(sx, s3.y);
  2422. p2Attributes.st.values.push(sx, s0.y);
  2423. p2Attributes.st.values.push(sx, s3.y);
  2424. for (j = i2 * 2; j < i2 * 2 + 2 * 2; ++j) {
  2425. p2Attributes.st.values.push(texCoords[j]);
  2426. }
  2427. }
  2428. index = p0Attributes.position.values.length / 3 - 4;
  2429. p0Indices.push(index, index + 2, index + 1);
  2430. p0Indices.push(index + 1, index + 2, index + 3);
  2431. index = p2Attributes.position.values.length / 3 - 4;
  2432. p2Indices.push(index, index + 2, index + 1);
  2433. p2Indices.push(index + 1, index + 2, index + 3);
  2434. } else {
  2435. var currentAttributes;
  2436. var currentIndices;
  2437. if (p0.y < 0.0) {
  2438. currentAttributes = westGeometry.attributes;
  2439. currentIndices = westGeometry.indices;
  2440. } else {
  2441. currentAttributes = eastGeometry.attributes;
  2442. currentIndices = eastGeometry.indices;
  2443. }
  2444. currentAttributes.position.values.push(p0.x, p0.y, p0.z);
  2445. currentAttributes.position.values.push(p0.x, p0.y, p0.z);
  2446. currentAttributes.position.values.push(p2.x, p2.y, p2.z);
  2447. currentAttributes.position.values.push(p2.x, p2.y, p2.z);
  2448. for (j = i * 3; j < i * 3 + 4 * 3; ++j) {
  2449. currentAttributes.prevPosition.values.push(prevPositions[j]);
  2450. currentAttributes.nextPosition.values.push(nextPositions[j]);
  2451. }
  2452. for (j = i * 2; j < i * 2 + 4 * 2; ++j) {
  2453. currentAttributes.expandAndWidth.values.push(expandAndWidths[j]);
  2454. if (defined.defined(texCoords)) {
  2455. currentAttributes.st.values.push(texCoords[j]);
  2456. }
  2457. }
  2458. if (defined.defined(colors)) {
  2459. for (j = i * 4; j < i * 4 + 4 * 4; ++j) {
  2460. currentAttributes.color.values.push(colors[j]);
  2461. }
  2462. }
  2463. index = currentAttributes.position.values.length / 3 - 4;
  2464. currentIndices.push(index, index + 2, index + 1);
  2465. currentIndices.push(index + 1, index + 2, index + 3);
  2466. }
  2467. }
  2468. if (intersectionFound) {
  2469. updateAdjacencyAfterSplit(westGeometry);
  2470. updateAdjacencyAfterSplit(eastGeometry);
  2471. }
  2472. updateInstanceAfterSplit(instance, westGeometry, eastGeometry);
  2473. }
  2474. /**
  2475. * Splits the instances's geometry, by introducing new vertices and indices,that
  2476. * intersect the International Date Line and Prime Meridian so that no primitives cross longitude
  2477. * -180/180 degrees. This is not required for 3D drawing, but is required for
  2478. * correcting drawing in 2D and Columbus view.
  2479. *
  2480. * @private
  2481. *
  2482. * @param {GeometryInstance} instance The instance to modify.
  2483. * @returns {GeometryInstance} The modified <code>instance</code> argument, with it's geometry split at the International Date Line.
  2484. *
  2485. * @example
  2486. * instance = Cesium.GeometryPipeline.splitLongitude(instance);
  2487. */
  2488. GeometryPipeline.splitLongitude = function(instance) {
  2489. //>>includeStart('debug', pragmas.debug);
  2490. if (!defined.defined(instance)) {
  2491. throw new Check.DeveloperError('instance is required.');
  2492. }
  2493. //>>includeEnd('debug');
  2494. var geometry = instance.geometry;
  2495. var boundingSphere = geometry.boundingSphere;
  2496. if (defined.defined(boundingSphere)) {
  2497. var minX = boundingSphere.center.x - boundingSphere.radius;
  2498. if (minX > 0 || Transforms.BoundingSphere.intersectPlane(boundingSphere, Plane.Plane.ORIGIN_ZX_PLANE) !== Transforms.Intersect.INTERSECTING) {
  2499. return instance;
  2500. }
  2501. }
  2502. if (geometry.geometryType !== GeometryAttribute.GeometryType.NONE) {
  2503. switch (geometry.geometryType) {
  2504. case GeometryAttribute.GeometryType.POLYLINES:
  2505. splitLongitudePolyline(instance);
  2506. break;
  2507. case GeometryAttribute.GeometryType.TRIANGLES:
  2508. splitLongitudeTriangles(instance);
  2509. break;
  2510. case GeometryAttribute.GeometryType.LINES:
  2511. splitLongitudeLines(instance);
  2512. break;
  2513. }
  2514. } else {
  2515. indexPrimitive(geometry);
  2516. if (geometry.primitiveType === GeometryAttribute.PrimitiveType.TRIANGLES) {
  2517. splitLongitudeTriangles(instance);
  2518. } else if (geometry.primitiveType === GeometryAttribute.PrimitiveType.LINES) {
  2519. splitLongitudeLines(instance);
  2520. }
  2521. }
  2522. return instance;
  2523. };
  2524. exports.GeometryPipeline = GeometryPipeline;
  2525. });