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