PrimitivePipeline.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  1. import BoundingSphere from "../Core/BoundingSphere.js";
  2. import ComponentDatatype from "../Core/ComponentDatatype.js";
  3. import defaultValue from "../Core/defaultValue.js";
  4. import defined from "../Core/defined.js";
  5. import DeveloperError from "../Core/DeveloperError.js";
  6. import Ellipsoid from "../Core/Ellipsoid.js";
  7. import GeographicProjection from "../Core/GeographicProjection.js";
  8. import Geometry from "../Core/Geometry.js";
  9. import GeometryAttribute from "../Core/GeometryAttribute.js";
  10. import GeometryAttributes from "../Core/GeometryAttributes.js";
  11. import GeometryPipeline from "../Core/GeometryPipeline.js";
  12. import IndexDatatype from "../Core/IndexDatatype.js";
  13. import Matrix4 from "../Core/Matrix4.js";
  14. import OffsetGeometryInstanceAttribute from "../Core/OffsetGeometryInstanceAttribute.js";
  15. import WebMercatorProjection from "../Core/WebMercatorProjection.js";
  16. function transformToWorldCoordinates(
  17. instances,
  18. primitiveModelMatrix,
  19. scene3DOnly
  20. ) {
  21. var toWorld = !scene3DOnly;
  22. var length = instances.length;
  23. var i;
  24. if (!toWorld && length > 1) {
  25. var modelMatrix = instances[0].modelMatrix;
  26. for (i = 1; i < length; ++i) {
  27. if (!Matrix4.equals(modelMatrix, instances[i].modelMatrix)) {
  28. toWorld = true;
  29. break;
  30. }
  31. }
  32. }
  33. if (toWorld) {
  34. for (i = 0; i < length; ++i) {
  35. if (defined(instances[i].geometry)) {
  36. GeometryPipeline.transformToWorldCoordinates(instances[i]);
  37. }
  38. }
  39. } else {
  40. // Leave geometry in local coordinate system; auto update model-matrix.
  41. Matrix4.multiplyTransformation(
  42. primitiveModelMatrix,
  43. instances[0].modelMatrix,
  44. primitiveModelMatrix
  45. );
  46. }
  47. }
  48. function addGeometryBatchId(geometry, batchId) {
  49. var attributes = geometry.attributes;
  50. var positionAttr = attributes.position;
  51. var numberOfComponents =
  52. positionAttr.values.length / positionAttr.componentsPerAttribute;
  53. attributes.batchId = new GeometryAttribute({
  54. componentDatatype: ComponentDatatype.FLOAT,
  55. componentsPerAttribute: 1,
  56. values: new Float32Array(numberOfComponents),
  57. });
  58. var values = attributes.batchId.values;
  59. for (var j = 0; j < numberOfComponents; ++j) {
  60. values[j] = batchId;
  61. }
  62. }
  63. function addBatchIds(instances) {
  64. var length = instances.length;
  65. for (var i = 0; i < length; ++i) {
  66. var instance = instances[i];
  67. if (defined(instance.geometry)) {
  68. addGeometryBatchId(instance.geometry, i);
  69. } else if (
  70. defined(instance.westHemisphereGeometry) &&
  71. defined(instance.eastHemisphereGeometry)
  72. ) {
  73. addGeometryBatchId(instance.westHemisphereGeometry, i);
  74. addGeometryBatchId(instance.eastHemisphereGeometry, i);
  75. }
  76. }
  77. }
  78. function geometryPipeline(parameters) {
  79. var instances = parameters.instances;
  80. var projection = parameters.projection;
  81. var uintIndexSupport = parameters.elementIndexUintSupported;
  82. var scene3DOnly = parameters.scene3DOnly;
  83. var vertexCacheOptimize = parameters.vertexCacheOptimize;
  84. var compressVertices = parameters.compressVertices;
  85. var modelMatrix = parameters.modelMatrix;
  86. var i;
  87. var geometry;
  88. var primitiveType;
  89. var length = instances.length;
  90. for (i = 0; i < length; ++i) {
  91. if (defined(instances[i].geometry)) {
  92. primitiveType = instances[i].geometry.primitiveType;
  93. break;
  94. }
  95. }
  96. //>>includeStart('debug', pragmas.debug);
  97. for (i = 1; i < length; ++i) {
  98. if (
  99. defined(instances[i].geometry) &&
  100. instances[i].geometry.primitiveType !== primitiveType
  101. ) {
  102. throw new DeveloperError(
  103. "All instance geometries must have the same primitiveType."
  104. );
  105. }
  106. }
  107. //>>includeEnd('debug');
  108. // Unify to world coordinates before combining.
  109. transformToWorldCoordinates(instances, modelMatrix, scene3DOnly);
  110. // Clip to IDL
  111. if (!scene3DOnly) {
  112. for (i = 0; i < length; ++i) {
  113. if (defined(instances[i].geometry)) {
  114. GeometryPipeline.splitLongitude(instances[i]);
  115. }
  116. }
  117. }
  118. addBatchIds(instances);
  119. // Optimize for vertex shader caches
  120. if (vertexCacheOptimize) {
  121. for (i = 0; i < length; ++i) {
  122. var instance = instances[i];
  123. if (defined(instance.geometry)) {
  124. GeometryPipeline.reorderForPostVertexCache(instance.geometry);
  125. GeometryPipeline.reorderForPreVertexCache(instance.geometry);
  126. } else if (
  127. defined(instance.westHemisphereGeometry) &&
  128. defined(instance.eastHemisphereGeometry)
  129. ) {
  130. GeometryPipeline.reorderForPostVertexCache(
  131. instance.westHemisphereGeometry
  132. );
  133. GeometryPipeline.reorderForPreVertexCache(
  134. instance.westHemisphereGeometry
  135. );
  136. GeometryPipeline.reorderForPostVertexCache(
  137. instance.eastHemisphereGeometry
  138. );
  139. GeometryPipeline.reorderForPreVertexCache(
  140. instance.eastHemisphereGeometry
  141. );
  142. }
  143. }
  144. }
  145. // Combine into single geometry for better rendering performance.
  146. var geometries = GeometryPipeline.combineInstances(instances);
  147. length = geometries.length;
  148. for (i = 0; i < length; ++i) {
  149. geometry = geometries[i];
  150. // Split positions for GPU RTE
  151. var attributes = geometry.attributes;
  152. var name;
  153. if (!scene3DOnly) {
  154. for (name in attributes) {
  155. if (
  156. attributes.hasOwnProperty(name) &&
  157. attributes[name].componentDatatype === ComponentDatatype.DOUBLE
  158. ) {
  159. var name3D = name + "3D";
  160. var name2D = name + "2D";
  161. // Compute 2D positions
  162. GeometryPipeline.projectTo2D(
  163. geometry,
  164. name,
  165. name3D,
  166. name2D,
  167. projection
  168. );
  169. if (defined(geometry.boundingSphere) && name === "position") {
  170. geometry.boundingSphereCV = BoundingSphere.fromVertices(
  171. geometry.attributes.position2D.values
  172. );
  173. }
  174. GeometryPipeline.encodeAttribute(
  175. geometry,
  176. name3D,
  177. name3D + "High",
  178. name3D + "Low"
  179. );
  180. GeometryPipeline.encodeAttribute(
  181. geometry,
  182. name2D,
  183. name2D + "High",
  184. name2D + "Low"
  185. );
  186. }
  187. }
  188. } else {
  189. for (name in attributes) {
  190. if (
  191. attributes.hasOwnProperty(name) &&
  192. attributes[name].componentDatatype === ComponentDatatype.DOUBLE
  193. ) {
  194. GeometryPipeline.encodeAttribute(
  195. geometry,
  196. name,
  197. name + "3DHigh",
  198. name + "3DLow"
  199. );
  200. }
  201. }
  202. }
  203. // oct encode and pack normals, compress texture coordinates
  204. if (compressVertices) {
  205. GeometryPipeline.compressVertices(geometry);
  206. }
  207. }
  208. if (!uintIndexSupport) {
  209. // Break into multiple geometries to fit within unsigned short indices if needed
  210. var splitGeometries = [];
  211. length = geometries.length;
  212. for (i = 0; i < length; ++i) {
  213. geometry = geometries[i];
  214. splitGeometries = splitGeometries.concat(
  215. GeometryPipeline.fitToUnsignedShortIndices(geometry)
  216. );
  217. }
  218. geometries = splitGeometries;
  219. }
  220. return geometries;
  221. }
  222. function createPickOffsets(instances, geometryName, geometries, pickOffsets) {
  223. var offset;
  224. var indexCount;
  225. var geometryIndex;
  226. var offsetIndex = pickOffsets.length - 1;
  227. if (offsetIndex >= 0) {
  228. var pickOffset = pickOffsets[offsetIndex];
  229. offset = pickOffset.offset + pickOffset.count;
  230. geometryIndex = pickOffset.index;
  231. indexCount = geometries[geometryIndex].indices.length;
  232. } else {
  233. offset = 0;
  234. geometryIndex = 0;
  235. indexCount = geometries[geometryIndex].indices.length;
  236. }
  237. var length = instances.length;
  238. for (var i = 0; i < length; ++i) {
  239. var instance = instances[i];
  240. var geometry = instance[geometryName];
  241. if (!defined(geometry)) {
  242. continue;
  243. }
  244. var count = geometry.indices.length;
  245. if (offset + count > indexCount) {
  246. offset = 0;
  247. indexCount = geometries[++geometryIndex].indices.length;
  248. }
  249. pickOffsets.push({
  250. index: geometryIndex,
  251. offset: offset,
  252. count: count,
  253. });
  254. offset += count;
  255. }
  256. }
  257. function createInstancePickOffsets(instances, geometries) {
  258. var pickOffsets = [];
  259. createPickOffsets(instances, "geometry", geometries, pickOffsets);
  260. createPickOffsets(
  261. instances,
  262. "westHemisphereGeometry",
  263. geometries,
  264. pickOffsets
  265. );
  266. createPickOffsets(
  267. instances,
  268. "eastHemisphereGeometry",
  269. geometries,
  270. pickOffsets
  271. );
  272. return pickOffsets;
  273. }
  274. /**
  275. * @private
  276. */
  277. var PrimitivePipeline = {};
  278. /**
  279. * @private
  280. */
  281. PrimitivePipeline.combineGeometry = function (parameters) {
  282. var geometries;
  283. var attributeLocations;
  284. var instances = parameters.instances;
  285. var length = instances.length;
  286. var pickOffsets;
  287. var offsetInstanceExtend;
  288. var hasOffset = false;
  289. if (length > 0) {
  290. geometries = geometryPipeline(parameters);
  291. if (geometries.length > 0) {
  292. attributeLocations = GeometryPipeline.createAttributeLocations(
  293. geometries[0]
  294. );
  295. if (parameters.createPickOffsets) {
  296. pickOffsets = createInstancePickOffsets(instances, geometries);
  297. }
  298. }
  299. if (
  300. defined(instances[0].attributes) &&
  301. defined(instances[0].attributes.offset)
  302. ) {
  303. offsetInstanceExtend = new Array(length);
  304. hasOffset = true;
  305. }
  306. }
  307. var boundingSpheres = new Array(length);
  308. var boundingSpheresCV = new Array(length);
  309. for (var i = 0; i < length; ++i) {
  310. var instance = instances[i];
  311. var geometry = instance.geometry;
  312. if (defined(geometry)) {
  313. boundingSpheres[i] = geometry.boundingSphere;
  314. boundingSpheresCV[i] = geometry.boundingSphereCV;
  315. if (hasOffset) {
  316. offsetInstanceExtend[i] = instance.geometry.offsetAttribute;
  317. }
  318. }
  319. var eastHemisphereGeometry = instance.eastHemisphereGeometry;
  320. var westHemisphereGeometry = instance.westHemisphereGeometry;
  321. if (defined(eastHemisphereGeometry) && defined(westHemisphereGeometry)) {
  322. if (
  323. defined(eastHemisphereGeometry.boundingSphere) &&
  324. defined(westHemisphereGeometry.boundingSphere)
  325. ) {
  326. boundingSpheres[i] = BoundingSphere.union(
  327. eastHemisphereGeometry.boundingSphere,
  328. westHemisphereGeometry.boundingSphere
  329. );
  330. }
  331. if (
  332. defined(eastHemisphereGeometry.boundingSphereCV) &&
  333. defined(westHemisphereGeometry.boundingSphereCV)
  334. ) {
  335. boundingSpheresCV[i] = BoundingSphere.union(
  336. eastHemisphereGeometry.boundingSphereCV,
  337. westHemisphereGeometry.boundingSphereCV
  338. );
  339. }
  340. }
  341. }
  342. return {
  343. geometries: geometries,
  344. modelMatrix: parameters.modelMatrix,
  345. attributeLocations: attributeLocations,
  346. pickOffsets: pickOffsets,
  347. offsetInstanceExtend: offsetInstanceExtend,
  348. boundingSpheres: boundingSpheres,
  349. boundingSpheresCV: boundingSpheresCV,
  350. };
  351. };
  352. function transferGeometry(geometry, transferableObjects) {
  353. var attributes = geometry.attributes;
  354. for (var name in attributes) {
  355. if (attributes.hasOwnProperty(name)) {
  356. var attribute = attributes[name];
  357. if (defined(attribute) && defined(attribute.values)) {
  358. transferableObjects.push(attribute.values.buffer);
  359. }
  360. }
  361. }
  362. if (defined(geometry.indices)) {
  363. transferableObjects.push(geometry.indices.buffer);
  364. }
  365. }
  366. function transferGeometries(geometries, transferableObjects) {
  367. var length = geometries.length;
  368. for (var i = 0; i < length; ++i) {
  369. transferGeometry(geometries[i], transferableObjects);
  370. }
  371. }
  372. // This function was created by simplifying packCreateGeometryResults into a count-only operation.
  373. function countCreateGeometryResults(items) {
  374. var count = 1;
  375. var length = items.length;
  376. for (var i = 0; i < length; i++) {
  377. var geometry = items[i];
  378. ++count;
  379. if (!defined(geometry)) {
  380. continue;
  381. }
  382. var attributes = geometry.attributes;
  383. count +=
  384. 7 +
  385. 2 * BoundingSphere.packedLength +
  386. (defined(geometry.indices) ? geometry.indices.length : 0);
  387. for (var property in attributes) {
  388. if (
  389. attributes.hasOwnProperty(property) &&
  390. defined(attributes[property])
  391. ) {
  392. var attribute = attributes[property];
  393. count += 5 + attribute.values.length;
  394. }
  395. }
  396. }
  397. return count;
  398. }
  399. /**
  400. * @private
  401. */
  402. PrimitivePipeline.packCreateGeometryResults = function (
  403. items,
  404. transferableObjects
  405. ) {
  406. var packedData = new Float64Array(countCreateGeometryResults(items));
  407. var stringTable = [];
  408. var stringHash = {};
  409. var length = items.length;
  410. var count = 0;
  411. packedData[count++] = length;
  412. for (var i = 0; i < length; i++) {
  413. var geometry = items[i];
  414. var validGeometry = defined(geometry);
  415. packedData[count++] = validGeometry ? 1.0 : 0.0;
  416. if (!validGeometry) {
  417. continue;
  418. }
  419. packedData[count++] = geometry.primitiveType;
  420. packedData[count++] = geometry.geometryType;
  421. packedData[count++] = defaultValue(geometry.offsetAttribute, -1);
  422. var validBoundingSphere = defined(geometry.boundingSphere) ? 1.0 : 0.0;
  423. packedData[count++] = validBoundingSphere;
  424. if (validBoundingSphere) {
  425. BoundingSphere.pack(geometry.boundingSphere, packedData, count);
  426. }
  427. count += BoundingSphere.packedLength;
  428. var validBoundingSphereCV = defined(geometry.boundingSphereCV) ? 1.0 : 0.0;
  429. packedData[count++] = validBoundingSphereCV;
  430. if (validBoundingSphereCV) {
  431. BoundingSphere.pack(geometry.boundingSphereCV, packedData, count);
  432. }
  433. count += BoundingSphere.packedLength;
  434. var attributes = geometry.attributes;
  435. var attributesToWrite = [];
  436. for (var property in attributes) {
  437. if (
  438. attributes.hasOwnProperty(property) &&
  439. defined(attributes[property])
  440. ) {
  441. attributesToWrite.push(property);
  442. if (!defined(stringHash[property])) {
  443. stringHash[property] = stringTable.length;
  444. stringTable.push(property);
  445. }
  446. }
  447. }
  448. packedData[count++] = attributesToWrite.length;
  449. for (var q = 0; q < attributesToWrite.length; q++) {
  450. var name = attributesToWrite[q];
  451. var attribute = attributes[name];
  452. packedData[count++] = stringHash[name];
  453. packedData[count++] = attribute.componentDatatype;
  454. packedData[count++] = attribute.componentsPerAttribute;
  455. packedData[count++] = attribute.normalize ? 1 : 0;
  456. packedData[count++] = attribute.values.length;
  457. packedData.set(attribute.values, count);
  458. count += attribute.values.length;
  459. }
  460. var indicesLength = defined(geometry.indices) ? geometry.indices.length : 0;
  461. packedData[count++] = indicesLength;
  462. if (indicesLength > 0) {
  463. packedData.set(geometry.indices, count);
  464. count += indicesLength;
  465. }
  466. }
  467. transferableObjects.push(packedData.buffer);
  468. return {
  469. stringTable: stringTable,
  470. packedData: packedData,
  471. };
  472. };
  473. /**
  474. * @private
  475. */
  476. PrimitivePipeline.unpackCreateGeometryResults = function (
  477. createGeometryResult
  478. ) {
  479. var stringTable = createGeometryResult.stringTable;
  480. var packedGeometry = createGeometryResult.packedData;
  481. var i;
  482. var result = new Array(packedGeometry[0]);
  483. var resultIndex = 0;
  484. var packedGeometryIndex = 1;
  485. while (packedGeometryIndex < packedGeometry.length) {
  486. var valid = packedGeometry[packedGeometryIndex++] === 1.0;
  487. if (!valid) {
  488. result[resultIndex++] = undefined;
  489. continue;
  490. }
  491. var primitiveType = packedGeometry[packedGeometryIndex++];
  492. var geometryType = packedGeometry[packedGeometryIndex++];
  493. var offsetAttribute = packedGeometry[packedGeometryIndex++];
  494. if (offsetAttribute === -1) {
  495. offsetAttribute = undefined;
  496. }
  497. var boundingSphere;
  498. var boundingSphereCV;
  499. var validBoundingSphere = packedGeometry[packedGeometryIndex++] === 1.0;
  500. if (validBoundingSphere) {
  501. boundingSphere = BoundingSphere.unpack(
  502. packedGeometry,
  503. packedGeometryIndex
  504. );
  505. }
  506. packedGeometryIndex += BoundingSphere.packedLength;
  507. var validBoundingSphereCV = packedGeometry[packedGeometryIndex++] === 1.0;
  508. if (validBoundingSphereCV) {
  509. boundingSphereCV = BoundingSphere.unpack(
  510. packedGeometry,
  511. packedGeometryIndex
  512. );
  513. }
  514. packedGeometryIndex += BoundingSphere.packedLength;
  515. var length;
  516. var values;
  517. var componentsPerAttribute;
  518. var attributes = new GeometryAttributes();
  519. var numAttributes = packedGeometry[packedGeometryIndex++];
  520. for (i = 0; i < numAttributes; i++) {
  521. var name = stringTable[packedGeometry[packedGeometryIndex++]];
  522. var componentDatatype = packedGeometry[packedGeometryIndex++];
  523. componentsPerAttribute = packedGeometry[packedGeometryIndex++];
  524. var normalize = packedGeometry[packedGeometryIndex++] !== 0;
  525. length = packedGeometry[packedGeometryIndex++];
  526. values = ComponentDatatype.createTypedArray(componentDatatype, length);
  527. for (var valuesIndex = 0; valuesIndex < length; valuesIndex++) {
  528. values[valuesIndex] = packedGeometry[packedGeometryIndex++];
  529. }
  530. attributes[name] = new GeometryAttribute({
  531. componentDatatype: componentDatatype,
  532. componentsPerAttribute: componentsPerAttribute,
  533. normalize: normalize,
  534. values: values,
  535. });
  536. }
  537. var indices;
  538. length = packedGeometry[packedGeometryIndex++];
  539. if (length > 0) {
  540. var numberOfVertices = values.length / componentsPerAttribute;
  541. indices = IndexDatatype.createTypedArray(numberOfVertices, length);
  542. for (i = 0; i < length; i++) {
  543. indices[i] = packedGeometry[packedGeometryIndex++];
  544. }
  545. }
  546. result[resultIndex++] = new Geometry({
  547. primitiveType: primitiveType,
  548. geometryType: geometryType,
  549. boundingSphere: boundingSphere,
  550. boundingSphereCV: boundingSphereCV,
  551. indices: indices,
  552. attributes: attributes,
  553. offsetAttribute: offsetAttribute,
  554. });
  555. }
  556. return result;
  557. };
  558. function packInstancesForCombine(instances, transferableObjects) {
  559. var length = instances.length;
  560. var packedData = new Float64Array(1 + length * 19);
  561. var count = 0;
  562. packedData[count++] = length;
  563. for (var i = 0; i < length; i++) {
  564. var instance = instances[i];
  565. Matrix4.pack(instance.modelMatrix, packedData, count);
  566. count += Matrix4.packedLength;
  567. if (defined(instance.attributes) && defined(instance.attributes.offset)) {
  568. var values = instance.attributes.offset.value;
  569. packedData[count] = values[0];
  570. packedData[count + 1] = values[1];
  571. packedData[count + 2] = values[2];
  572. }
  573. count += 3;
  574. }
  575. transferableObjects.push(packedData.buffer);
  576. return packedData;
  577. }
  578. function unpackInstancesForCombine(data) {
  579. var packedInstances = data;
  580. var result = new Array(packedInstances[0]);
  581. var count = 0;
  582. var i = 1;
  583. while (i < packedInstances.length) {
  584. var modelMatrix = Matrix4.unpack(packedInstances, i);
  585. var attributes;
  586. i += Matrix4.packedLength;
  587. if (defined(packedInstances[i])) {
  588. attributes = {
  589. offset: new OffsetGeometryInstanceAttribute(
  590. packedInstances[i],
  591. packedInstances[i + 1],
  592. packedInstances[i + 2]
  593. ),
  594. };
  595. }
  596. i += 3;
  597. result[count++] = {
  598. modelMatrix: modelMatrix,
  599. attributes: attributes,
  600. };
  601. }
  602. return result;
  603. }
  604. /**
  605. * @private
  606. */
  607. PrimitivePipeline.packCombineGeometryParameters = function (
  608. parameters,
  609. transferableObjects
  610. ) {
  611. var createGeometryResults = parameters.createGeometryResults;
  612. var length = createGeometryResults.length;
  613. for (var i = 0; i < length; i++) {
  614. transferableObjects.push(createGeometryResults[i].packedData.buffer);
  615. }
  616. return {
  617. createGeometryResults: parameters.createGeometryResults,
  618. packedInstances: packInstancesForCombine(
  619. parameters.instances,
  620. transferableObjects
  621. ),
  622. ellipsoid: parameters.ellipsoid,
  623. isGeographic: parameters.projection instanceof GeographicProjection,
  624. elementIndexUintSupported: parameters.elementIndexUintSupported,
  625. scene3DOnly: parameters.scene3DOnly,
  626. vertexCacheOptimize: parameters.vertexCacheOptimize,
  627. compressVertices: parameters.compressVertices,
  628. modelMatrix: parameters.modelMatrix,
  629. createPickOffsets: parameters.createPickOffsets,
  630. };
  631. };
  632. /**
  633. * @private
  634. */
  635. PrimitivePipeline.unpackCombineGeometryParameters = function (
  636. packedParameters
  637. ) {
  638. var instances = unpackInstancesForCombine(packedParameters.packedInstances);
  639. var createGeometryResults = packedParameters.createGeometryResults;
  640. var length = createGeometryResults.length;
  641. var instanceIndex = 0;
  642. for (var resultIndex = 0; resultIndex < length; resultIndex++) {
  643. var geometries = PrimitivePipeline.unpackCreateGeometryResults(
  644. createGeometryResults[resultIndex]
  645. );
  646. var geometriesLength = geometries.length;
  647. for (
  648. var geometryIndex = 0;
  649. geometryIndex < geometriesLength;
  650. geometryIndex++
  651. ) {
  652. var geometry = geometries[geometryIndex];
  653. var instance = instances[instanceIndex];
  654. instance.geometry = geometry;
  655. ++instanceIndex;
  656. }
  657. }
  658. var ellipsoid = Ellipsoid.clone(packedParameters.ellipsoid);
  659. var projection = packedParameters.isGeographic
  660. ? new GeographicProjection(ellipsoid)
  661. : new WebMercatorProjection(ellipsoid);
  662. return {
  663. instances: instances,
  664. ellipsoid: ellipsoid,
  665. projection: projection,
  666. elementIndexUintSupported: packedParameters.elementIndexUintSupported,
  667. scene3DOnly: packedParameters.scene3DOnly,
  668. vertexCacheOptimize: packedParameters.vertexCacheOptimize,
  669. compressVertices: packedParameters.compressVertices,
  670. modelMatrix: Matrix4.clone(packedParameters.modelMatrix),
  671. createPickOffsets: packedParameters.createPickOffsets,
  672. };
  673. };
  674. function packBoundingSpheres(boundingSpheres) {
  675. var length = boundingSpheres.length;
  676. var bufferLength = 1 + (BoundingSphere.packedLength + 1) * length;
  677. var buffer = new Float32Array(bufferLength);
  678. var bufferIndex = 0;
  679. buffer[bufferIndex++] = length;
  680. for (var i = 0; i < length; ++i) {
  681. var bs = boundingSpheres[i];
  682. if (!defined(bs)) {
  683. buffer[bufferIndex++] = 0.0;
  684. } else {
  685. buffer[bufferIndex++] = 1.0;
  686. BoundingSphere.pack(boundingSpheres[i], buffer, bufferIndex);
  687. }
  688. bufferIndex += BoundingSphere.packedLength;
  689. }
  690. return buffer;
  691. }
  692. function unpackBoundingSpheres(buffer) {
  693. var result = new Array(buffer[0]);
  694. var count = 0;
  695. var i = 1;
  696. while (i < buffer.length) {
  697. if (buffer[i++] === 1.0) {
  698. result[count] = BoundingSphere.unpack(buffer, i);
  699. }
  700. ++count;
  701. i += BoundingSphere.packedLength;
  702. }
  703. return result;
  704. }
  705. /**
  706. * @private
  707. */
  708. PrimitivePipeline.packCombineGeometryResults = function (
  709. results,
  710. transferableObjects
  711. ) {
  712. if (defined(results.geometries)) {
  713. transferGeometries(results.geometries, transferableObjects);
  714. }
  715. var packedBoundingSpheres = packBoundingSpheres(results.boundingSpheres);
  716. var packedBoundingSpheresCV = packBoundingSpheres(results.boundingSpheresCV);
  717. transferableObjects.push(
  718. packedBoundingSpheres.buffer,
  719. packedBoundingSpheresCV.buffer
  720. );
  721. return {
  722. geometries: results.geometries,
  723. attributeLocations: results.attributeLocations,
  724. modelMatrix: results.modelMatrix,
  725. pickOffsets: results.pickOffsets,
  726. offsetInstanceExtend: results.offsetInstanceExtend,
  727. boundingSpheres: packedBoundingSpheres,
  728. boundingSpheresCV: packedBoundingSpheresCV,
  729. };
  730. };
  731. /**
  732. * @private
  733. */
  734. PrimitivePipeline.unpackCombineGeometryResults = function (packedResult) {
  735. return {
  736. geometries: packedResult.geometries,
  737. attributeLocations: packedResult.attributeLocations,
  738. modelMatrix: packedResult.modelMatrix,
  739. pickOffsets: packedResult.pickOffsets,
  740. offsetInstanceExtend: packedResult.offsetInstanceExtend,
  741. boundingSpheres: unpackBoundingSpheres(packedResult.boundingSpheres),
  742. boundingSpheresCV: unpackBoundingSpheres(packedResult.boundingSpheresCV),
  743. };
  744. };
  745. export default PrimitivePipeline;