PrimitivePipeline.js 27 KB

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