GeometryPipeline.js 91 KB

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