12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013 |
- /*global define*/
- define([
- '../Core/BoundingSphere',
- '../Core/Color',
- '../Core/ComponentDatatype',
- '../Core/defaultValue',
- '../Core/defined',
- '../Core/DeveloperError',
- '../Core/Ellipsoid',
- '../Core/FeatureDetection',
- '../Core/GeographicProjection',
- '../Core/Geometry',
- '../Core/GeometryAttribute',
- '../Core/GeometryPipeline',
- '../Core/IndexDatatype',
- '../Core/Matrix4',
- '../Core/WebMercatorProjection'
- ], function(
- BoundingSphere,
- Color,
- ComponentDatatype,
- defaultValue,
- defined,
- DeveloperError,
- Ellipsoid,
- FeatureDetection,
- GeographicProjection,
- Geometry,
- GeometryAttribute,
- GeometryPipeline,
- IndexDatatype,
- Matrix4,
- WebMercatorProjection) {
- "use strict";
- // Bail out if the browser doesn't support typed arrays, to prevent the setup function
- // from failing, since we won't be able to create a WebGL context anyway.
- if (!FeatureDetection.supportsTypedArrays()) {
- return {};
- }
- function transformToWorldCoordinates(instances, primitiveModelMatrix, scene3DOnly) {
- var toWorld = !scene3DOnly;
- var length = instances.length;
- var i;
- if (!toWorld && (length > 1)) {
- var modelMatrix = instances[0].modelMatrix;
- for (i = 1; i < length; ++i) {
- if (!Matrix4.equals(modelMatrix, instances[i].modelMatrix)) {
- toWorld = true;
- break;
- }
- }
- }
- if (toWorld) {
- for (i = 0; i < length; ++i) {
- GeometryPipeline.transformToWorldCoordinates(instances[i]);
- }
- } else {
- // Leave geometry in local coordinate system; auto update model-matrix.
- Matrix4.multiplyTransformation(primitiveModelMatrix, instances[0].modelMatrix, primitiveModelMatrix);
- }
- }
- function addGeometryPickColor(geometry, pickColor) {
- var attributes = geometry.attributes;
- var positionAttr = attributes.position;
- var numberOfComponents = 4 * (positionAttr.values.length / positionAttr.componentsPerAttribute);
- attributes.pickColor = new GeometryAttribute({
- componentDatatype : ComponentDatatype.UNSIGNED_BYTE,
- componentsPerAttribute : 4,
- normalize : true,
- values : new Uint8Array(numberOfComponents)
- });
- var red = Color.floatToByte(pickColor.red);
- var green = Color.floatToByte(pickColor.green);
- var blue = Color.floatToByte(pickColor.blue);
- var alpha = Color.floatToByte(pickColor.alpha);
- var values = attributes.pickColor.values;
- for (var j = 0; j < numberOfComponents; j += 4) {
- values[j] = red;
- values[j + 1] = green;
- values[j + 2] = blue;
- values[j + 3] = alpha;
- }
- }
- function addPickColorAttribute(instances, pickIds) {
- var length = instances.length;
- for (var i = 0; i < length; ++i) {
- var instance = instances[i];
- var pickColor = pickIds[i];
- if (defined(instance.geometry)) {
- addGeometryPickColor(instance.geometry, pickColor);
- } else {
- addGeometryPickColor(instance.westHemisphereGeometry, pickColor);
- addGeometryPickColor(instance.eastHemisphereGeometry, pickColor);
- }
- }
- }
- function getCommonPerInstanceAttributeNames(instances) {
- var length = instances.length;
- var attributesInAllInstances = [];
- var attributes0 = instances[0].attributes;
- var name;
- for (name in attributes0) {
- if (attributes0.hasOwnProperty(name)) {
- var attribute = attributes0[name];
- var inAllInstances = true;
- // Does this same attribute exist in all instances?
- for (var i = 1; i < length; ++i) {
- var otherAttribute = instances[i].attributes[name];
- if (!defined(otherAttribute) ||
- (attribute.componentDatatype !== otherAttribute.componentDatatype) ||
- (attribute.componentsPerAttribute !== otherAttribute.componentsPerAttribute) ||
- (attribute.normalize !== otherAttribute.normalize)) {
- inAllInstances = false;
- break;
- }
- }
- if (inAllInstances) {
- attributesInAllInstances.push(name);
- }
- }
- }
- return attributesInAllInstances;
- }
- function addPerInstanceAttributesToGeometry(instanceAttributes, geometry, names) {
- var numberOfVertices = Geometry.computeNumberOfVertices(geometry);
- var namesLength = names.length;
- for (var j = 0; j < namesLength; ++j) {
- var name = names[j];
- var attribute = instanceAttributes[name];
- var componentDatatype = attribute.componentDatatype;
- var value = attribute.value;
- var componentsPerAttribute = value.length;
- var buffer = ComponentDatatype.createTypedArray(componentDatatype, numberOfVertices * componentsPerAttribute);
- for (var k = 0; k < numberOfVertices; ++k) {
- buffer.set(value, k * componentsPerAttribute);
- }
- geometry.attributes[name] = new GeometryAttribute({
- componentDatatype : componentDatatype,
- componentsPerAttribute : componentsPerAttribute,
- normalize : attribute.normalize,
- values : buffer
- });
- }
- }
- function addPerInstanceAttributes(instances, names) {
- var length = instances.length;
- for (var i = 0; i < length; ++i) {
- var instance = instances[i];
- var instanceAttributes = instance.attributes;
- if (defined(instance.geometry)) {
- addPerInstanceAttributesToGeometry(instanceAttributes, instance.geometry, names);
- } else {
- addPerInstanceAttributesToGeometry(instanceAttributes, instance.westHemisphereGeometry, names);
- addPerInstanceAttributesToGeometry(instanceAttributes, instance.eastHemisphereGeometry, names);
- }
- }
- }
- function geometryPipeline(parameters) {
- var instances = parameters.instances;
- var pickIds = parameters.pickIds;
- var projection = parameters.projection;
- var uintIndexSupport = parameters.elementIndexUintSupported;
- var scene3DOnly = parameters.scene3DOnly;
- var allowPicking = parameters.allowPicking;
- var vertexCacheOptimize = parameters.vertexCacheOptimize;
- var compressVertices = parameters.compressVertices;
- var modelMatrix = parameters.modelMatrix;
- var i;
- var geometry;
- var length = instances.length;
- var primitiveType = instances[0].geometry.primitiveType;
- //>>includeStart('debug', pragmas.debug);
- for (i = 1; i < length; ++i) {
- if (instances[i].geometry.primitiveType !== primitiveType) {
- throw new DeveloperError('All instance geometries must have the same primitiveType.');
- }
- }
- //>>includeEnd('debug');
- // Unify to world coordinates before combining.
- transformToWorldCoordinates(instances, modelMatrix, scene3DOnly);
- // Clip to IDL
- if (!scene3DOnly) {
- for (i = 0; i < length; ++i) {
- GeometryPipeline.splitLongitude(instances[i]);
- }
- }
- // Add pickColor attribute for picking individual instances
- if (allowPicking) {
- addPickColorAttribute(instances, pickIds);
- }
- // add attributes to the geometry for each per-instance attribute
- var perInstanceAttributeNames = getCommonPerInstanceAttributeNames(instances);
- addPerInstanceAttributes(instances, perInstanceAttributeNames);
- // Optimize for vertex shader caches
- if (vertexCacheOptimize) {
- for (i = 0; i < length; ++i) {
- var instance = instances[i];
- if (defined(instance.geometry)) {
- GeometryPipeline.reorderForPostVertexCache(instance.geometry);
- GeometryPipeline.reorderForPreVertexCache(instance.geometry);
- } else {
- GeometryPipeline.reorderForPostVertexCache(instance.westHemisphereGeometry);
- GeometryPipeline.reorderForPreVertexCache(instance.westHemisphereGeometry);
- GeometryPipeline.reorderForPostVertexCache(instance.eastHemisphereGeometry);
- GeometryPipeline.reorderForPreVertexCache(instance.eastHemisphereGeometry);
- }
- }
- }
- // Combine into single geometry for better rendering performance.
- var geometries = GeometryPipeline.combineInstances(instances);
- length = geometries.length;
- for (i = 0; i < length; ++i) {
- geometry = geometries[i];
- // Split positions for GPU RTE
- var attributes = geometry.attributes;
- var name;
- if (!scene3DOnly) {
- for (name in attributes) {
- if (attributes.hasOwnProperty(name) && attributes[name].componentDatatype === ComponentDatatype.DOUBLE) {
- var name3D = name + '3D';
- var name2D = name + '2D';
- // Compute 2D positions
- GeometryPipeline.projectTo2D(geometry, name, name3D, name2D, projection);
- if (defined(geometry.boundingSphere) && name === 'position') {
- geometry.boundingSphereCV = BoundingSphere.fromVertices(geometry.attributes.position2D.values);
- }
- GeometryPipeline.encodeAttribute(geometry, name3D, name3D + 'High', name3D + 'Low');
- GeometryPipeline.encodeAttribute(geometry, name2D, name2D + 'High', name2D + 'Low');
- }
- }
- } else {
- for (name in attributes) {
- if (attributes.hasOwnProperty(name) && attributes[name].componentDatatype === ComponentDatatype.DOUBLE) {
- GeometryPipeline.encodeAttribute(geometry, name, name + '3DHigh', name + '3DLow');
- }
- }
- }
- // oct encode and pack normals, compress texture coordinates
- if (compressVertices) {
- GeometryPipeline.compressVertices(geometry);
- }
- }
- if (!uintIndexSupport) {
- // Break into multiple geometries to fit within unsigned short indices if needed
- var splitGeometries = [];
- length = geometries.length;
- for (i = 0; i < length; ++i) {
- geometry = geometries[i];
- splitGeometries = splitGeometries.concat(GeometryPipeline.fitToUnsignedShortIndices(geometry));
- }
- geometries = splitGeometries;
- }
- return geometries;
- }
- function createPerInstanceVAAttributes(geometry, attributeLocations, names) {
- var vaAttributes = [];
- var attributes = geometry.attributes;
- var length = names.length;
- for (var i = 0; i < length; ++i) {
- var name = names[i];
- var attribute = attributes[name];
- var componentDatatype = attribute.componentDatatype;
- if (componentDatatype === ComponentDatatype.DOUBLE) {
- componentDatatype = ComponentDatatype.FLOAT;
- }
- var typedArray = ComponentDatatype.createTypedArray(componentDatatype, attribute.values);
- vaAttributes.push({
- index : attributeLocations[name],
- componentDatatype : componentDatatype,
- componentsPerAttribute : attribute.componentsPerAttribute,
- normalize : attribute.normalize,
- values : typedArray
- });
- delete attributes[name];
- }
- return vaAttributes;
- }
- function computePerInstanceAttributeLocationsForGeometry(instanceIndex, geometry, instanceAttributes, names, attributeLocations, vertexArrays, indices, offsets, vaIndices) {
- var numberOfVertices = Geometry.computeNumberOfVertices(geometry);
- var namesLength = names.length;
- for (var j = 0; j < namesLength; ++j) {
- var name = names[j];
- var index = attributeLocations[name];
- var tempVertexCount = numberOfVertices;
- while (tempVertexCount > 0) {
- var vaIndex = defaultValue(vaIndices[name], 0);
- var va = vertexArrays[vaIndex];
- var vaLength = va.length;
- var attribute;
- for (var k = 0; k < vaLength; ++k) {
- attribute = va[k];
- if (attribute.index === index) {
- break;
- }
- }
- if (!defined(indices[instanceIndex])) {
- indices[instanceIndex] = {};
- }
- if (!defined(indices[instanceIndex][name])) {
- indices[instanceIndex][name] = {
- dirty : false,
- value : instanceAttributes[name].value,
- indices : []
- };
- }
- var size = attribute.values.length / attribute.componentsPerAttribute;
- var offset = defaultValue(offsets[name], 0);
- var count;
- if (offset + tempVertexCount < size) {
- count = tempVertexCount;
- indices[instanceIndex][name].indices.push({
- attribute : attribute,
- offset : offset,
- count : count
- });
- offsets[name] = offset + tempVertexCount;
- } else {
- count = size - offset;
- indices[instanceIndex][name].indices.push({
- attribute : attribute,
- offset : offset,
- count : count
- });
- offsets[name] = 0;
- vaIndices[name] = vaIndex + 1;
- }
- tempVertexCount -= count;
- }
- }
- }
- function computePerInstanceAttributeLocations(instances, vertexArrays, attributeLocations, names) {
- var indices = [];
- var length = instances.length;
- var offsets = {};
- var vaIndices = {};
- var i;
- var instance;
- var attributes;
- for (i = 0; i < length; ++i) {
- instance = instances[i];
- attributes = instance.attributes;
- if (defined(instance.geometry)) {
- computePerInstanceAttributeLocationsForGeometry(i, instance.geometry, attributes, names, attributeLocations, vertexArrays, indices, offsets, vaIndices);
- }
- }
- for (i = 0; i < length; ++i) {
- instance = instances[i];
- attributes = instance.attributes;
- if (defined(instance.westHemisphereGeometry)) {
- computePerInstanceAttributeLocationsForGeometry(i, instance.westHemisphereGeometry, attributes, names, attributeLocations, vertexArrays, indices, offsets, vaIndices);
- }
- }
- for (i = 0; i < length; ++i) {
- instance = instances[i];
- attributes = instance.attributes;
- if (defined(instance.eastHemisphereGeometry)) {
- computePerInstanceAttributeLocationsForGeometry(i, instance.eastHemisphereGeometry, attributes, names, attributeLocations, vertexArrays, indices, offsets, vaIndices);
- }
- }
- return indices;
- }
- /**
- * @private
- */
- var PrimitivePipeline = {};
- /**
- * @private
- */
- PrimitivePipeline.combineGeometry = function(parameters) {
- var geometries = geometryPipeline(parameters);
- var attributeLocations = GeometryPipeline.createAttributeLocations(geometries[0]);
- var instances = parameters.instances;
- var perInstanceAttributeNames = getCommonPerInstanceAttributeNames(instances);
- var perInstanceAttributes = [];
- var length = geometries.length;
- for (var i = 0; i < length; ++i) {
- var geometry = geometries[i];
- perInstanceAttributes.push(createPerInstanceVAAttributes(geometry, attributeLocations, perInstanceAttributeNames));
- }
- var indices = computePerInstanceAttributeLocations(instances, perInstanceAttributes, attributeLocations, perInstanceAttributeNames);
- return {
- geometries : geometries,
- modelMatrix : parameters.modelMatrix,
- attributeLocations : attributeLocations,
- vaAttributes : perInstanceAttributes,
- vaAttributeLocations : indices
- };
- };
- function transferGeometry(geometry, transferableObjects) {
- var attributes = geometry.attributes;
- for ( var name in attributes) {
- if (attributes.hasOwnProperty(name)) {
- var attribute = attributes[name];
- if (defined(attribute) && defined(attribute.values)) {
- transferableObjects.push(attribute.values.buffer);
- }
- }
- }
- if (defined(geometry.indices)) {
- transferableObjects.push(geometry.indices.buffer);
- }
- }
- function transferGeometries(geometries, transferableObjects) {
- var length = geometries.length;
- for (var i = 0; i < length; ++i) {
- transferGeometry(geometries[i], transferableObjects);
- }
- }
- /**
- * @private
- */
- function transferPerInstanceAttributes(perInstanceAttributes, transferableObjects) {
- var length = perInstanceAttributes.length;
- for (var i = 0; i < length; ++i) {
- var vaAttributes = perInstanceAttributes[i];
- var vaLength = vaAttributes.length;
- for (var j = 0; j < vaLength; ++j) {
- transferableObjects.push(vaAttributes[j].values.buffer);
- }
- }
- }
- // This function was created by simplifying packCreateGeometryResults into a count-only operation.
- function countCreateGeometryResults(items) {
- var count = 1;
- var length = items.length;
- for (var i = 0; i < length; i++) {
- var geometry = items[i];
- var attributes = geometry.attributes;
- count += 6 + 2 * BoundingSphere.packedLength + (defined(geometry.indices) ? geometry.indices.length : 0);
- for ( var property in attributes) {
- if (attributes.hasOwnProperty(property) && defined(attributes[property])) {
- var attribute = attributes[property];
- count += 5 + attribute.values.length;
- }
- }
- }
- return count;
- }
- /**
- * @private
- */
- PrimitivePipeline.packCreateGeometryResults = function(items, transferableObjects) {
- var packedData = new Float64Array(countCreateGeometryResults(items));
- var stringTable = [];
- var stringHash = {};
- var length = items.length;
- var count = 0;
- packedData[count++] = length;
- for (var i = 0; i < length; i++) {
- var geometry = items[i];
- packedData[count++] = geometry.primitiveType;
- packedData[count++] = geometry.geometryType;
- var validBoundingSphere = defined(geometry.boundingSphere) ? 1.0 : 0.0;
- packedData[count++] = validBoundingSphere;
- if (validBoundingSphere) {
- BoundingSphere.pack(geometry.boundingSphere, packedData, count);
- }
- count += BoundingSphere.packedLength;
- var validBoundingSphereCV = defined(geometry.boundingSphereCV) ? 1.0 : 0.0;
- packedData[count++] = validBoundingSphereCV;
- if (validBoundingSphereCV) {
- BoundingSphere.pack(geometry.boundingSphereCV, packedData, count);
- }
- count += BoundingSphere.packedLength;
- var attributes = geometry.attributes;
- var attributesToWrite = [];
- for ( var property in attributes) {
- if (attributes.hasOwnProperty(property) && defined(attributes[property])) {
- attributesToWrite.push(property);
- if (!defined(stringHash[property])) {
- stringHash[property] = stringTable.length;
- stringTable.push(property);
- }
- }
- }
- packedData[count++] = attributesToWrite.length;
- for (var q = 0; q < attributesToWrite.length; q++) {
- var name = attributesToWrite[q];
- var attribute = attributes[name];
- packedData[count++] = stringHash[name];
- packedData[count++] = attribute.componentDatatype;
- packedData[count++] = attribute.componentsPerAttribute;
- packedData[count++] = attribute.normalize ? 1 : 0;
- packedData[count++] = attribute.values.length;
- packedData.set(attribute.values, count);
- count += attribute.values.length;
- }
- var indicesLength = defined(geometry.indices) ? geometry.indices.length : 0;
- packedData[count++] = indicesLength;
- if (indicesLength > 0) {
- packedData.set(geometry.indices, count);
- count += indicesLength;
- }
- }
- transferableObjects.push(packedData.buffer);
- return {
- stringTable : stringTable,
- packedData : packedData
- };
- };
- /**
- * @private
- */
- PrimitivePipeline.unpackCreateGeometryResults = function(createGeometryResult) {
- var stringTable = createGeometryResult.stringTable;
- var packedGeometry = createGeometryResult.packedData;
- var i;
- var result = new Array(packedGeometry[0]);
- var resultIndex = 0;
- var packedGeometryIndex = 1;
- while (packedGeometryIndex < packedGeometry.length) {
- var primitiveType = packedGeometry[packedGeometryIndex++];
- var geometryType = packedGeometry[packedGeometryIndex++];
- var boundingSphere;
- var boundingSphereCV;
- var validBoundingSphere = packedGeometry[packedGeometryIndex++] === 1.0;
- if (validBoundingSphere) {
- boundingSphere = BoundingSphere.unpack(packedGeometry, packedGeometryIndex);
- }
- packedGeometryIndex += BoundingSphere.packedLength;
- var validBoundingSphereCV = packedGeometry[packedGeometryIndex++] === 1.0;
- if (validBoundingSphereCV) {
- boundingSphereCV = BoundingSphere.unpack(packedGeometry, packedGeometryIndex);
- }
- packedGeometryIndex += BoundingSphere.packedLength;
- var length;
- var values;
- var componentsPerAttribute;
- var attributes = {};
- var numAttributes = packedGeometry[packedGeometryIndex++];
- for (i = 0; i < numAttributes; i++) {
- var name = stringTable[packedGeometry[packedGeometryIndex++]];
- var componentDatatype = packedGeometry[packedGeometryIndex++];
- componentsPerAttribute = packedGeometry[packedGeometryIndex++];
- var normalize = packedGeometry[packedGeometryIndex++] !== 0;
- length = packedGeometry[packedGeometryIndex++];
- values = ComponentDatatype.createTypedArray(componentDatatype, length);
- for (var valuesIndex = 0; valuesIndex < length; valuesIndex++) {
- values[valuesIndex] = packedGeometry[packedGeometryIndex++];
- }
- attributes[name] = new GeometryAttribute({
- componentDatatype : componentDatatype,
- componentsPerAttribute : componentsPerAttribute,
- normalize : normalize,
- values : values
- });
- }
- var indices;
- length = packedGeometry[packedGeometryIndex++];
- if (length > 0) {
- var numberOfVertices = values.length / componentsPerAttribute;
- indices = IndexDatatype.createTypedArray(numberOfVertices, length);
- for (i = 0; i < length; i++) {
- indices[i] = packedGeometry[packedGeometryIndex++];
- }
- }
- result[resultIndex++] = new Geometry({
- primitiveType : primitiveType,
- geometryType : geometryType,
- boundingSphere : boundingSphere,
- indices : indices,
- attributes : attributes
- });
- }
- return result;
- };
- function packPickIds(pickIds, transferableObjects) {
- var length = pickIds.length;
- var packedPickIds = new Uint32Array(pickIds.length);
- for (var i = 0; i < length; ++i) {
- packedPickIds[i] = pickIds[i].toRgba();
- }
- transferableObjects.push(packedPickIds.buffer);
- return packedPickIds;
- }
- function unpackPickIds(packedPickIds) {
- var length = packedPickIds.length;
- var pickIds = new Array(length);
- for (var i = 0; i < length; i++) {
- pickIds[i] = Color.fromRgba(packedPickIds[i]);
- }
- return pickIds;
- }
- // This function was created by simplifying packInstancesForCombine into a count-only operation.
- function countInstancesForCombine(instances) {
- var length = instances.length;
- var count = 1 + (length * 17);
- for (var i = 0; i < length; i++) {
- var attributes = instances[i].attributes;
- for ( var property in attributes) {
- if (attributes.hasOwnProperty(property) && defined(attributes[property])) {
- var attribute = attributes[property];
- count += 5 + attribute.value.length;
- }
- }
- }
- return count;
- }
- function packInstancesForCombine(instances, transferableObjects) {
- var packedData = new Float64Array(countInstancesForCombine(instances));
- var stringHash = {};
- var stringTable = [];
- var length = instances.length;
- var count = 0;
- packedData[count++] = length;
- for (var i = 0; i < length; i++) {
- var instance = instances[i];
- Matrix4.pack(instance.modelMatrix, packedData, count);
- count += Matrix4.packedLength;
- var attributes = instance.attributes;
- var attributesToWrite = [];
- for ( var property in attributes) {
- if (attributes.hasOwnProperty(property) && defined(attributes[property])) {
- attributesToWrite.push(property);
- if (!defined(stringHash[property])) {
- stringHash[property] = stringTable.length;
- stringTable.push(property);
- }
- }
- }
- packedData[count++] = attributesToWrite.length;
- for (var q = 0; q < attributesToWrite.length; q++) {
- var name = attributesToWrite[q];
- var attribute = attributes[name];
- packedData[count++] = stringHash[name];
- packedData[count++] = attribute.componentDatatype;
- packedData[count++] = attribute.componentsPerAttribute;
- packedData[count++] = attribute.normalize;
- packedData[count++] = attribute.value.length;
- packedData.set(attribute.value, count);
- count += attribute.value.length;
- }
- }
- transferableObjects.push(packedData.buffer);
- return {
- stringTable : stringTable,
- packedData : packedData
- };
- }
- function unpackInstancesForCombine(data) {
- var packedInstances = data.packedData;
- var stringTable = data.stringTable;
- var result = new Array(packedInstances[0]);
- var count = 0;
- var i = 1;
- while (i < packedInstances.length) {
- var modelMatrix = Matrix4.unpack(packedInstances, i);
- i += Matrix4.packedLength;
- var attributes = {};
- var numAttributes = packedInstances[i++];
- for (var x = 0; x < numAttributes; x++) {
- var name = stringTable[packedInstances[i++]];
- var componentDatatype = packedInstances[i++];
- var componentsPerAttribute = packedInstances[i++];
- var normalize = packedInstances[i++] !== 0;
- var length = packedInstances[i++];
- var value = ComponentDatatype.createTypedArray(componentDatatype, length);
- for (var valueIndex = 0; valueIndex < length; valueIndex++) {
- value[valueIndex] = packedInstances[i++];
- }
- attributes[name] = {
- componentDatatype : componentDatatype,
- componentsPerAttribute : componentsPerAttribute,
- normalize : normalize,
- value : value
- };
- }
- result[count++] = {
- attributes : attributes,
- modelMatrix : modelMatrix
- };
- }
- return result;
- }
- // This function was created by simplifying packAttributeLocations into a count-only operation.
- function countAttributeLocations(attributeLocations) {
- var length = attributeLocations.length;
- var count = 1 + length;
- for (var i = 0; i < length; i++) {
- var instance = attributeLocations[i];
- for ( var propertyName in instance) {
- if (instance.hasOwnProperty(propertyName) && defined(instance[propertyName])) {
- var property = instance[propertyName];
- count += 3 + (property.indices.length * 3) + property.value.length;
- }
- }
- }
- return count;
- }
- function packAttributeLocations(attributeLocations, transferableObjects) {
- var packedData = new Float64Array(countAttributeLocations(attributeLocations));
- var stringTable = [];
- var attributeTable = [];
- var stringHash = {};
- var length = attributeLocations.length;
- var count = 0;
- packedData[count++] = length;
- for (var i = 0; i < length; i++) {
- var instance = attributeLocations[i];
- var propertiesToWrite = [];
- for ( var propertyName in instance) {
- if (instance.hasOwnProperty(propertyName) && defined(instance[propertyName])) {
- propertiesToWrite.push(propertyName);
- if (!defined(stringHash[propertyName])) {
- stringHash[propertyName] = stringTable.length;
- stringTable.push(propertyName);
- }
- }
- }
- packedData[count++] = propertiesToWrite.length;
- for (var q = 0; q < propertiesToWrite.length; q++) {
- var name = propertiesToWrite[q];
- var property = instance[name];
- packedData[count++] = stringHash[name];
- var indices = property.indices;
- var indicesLength = indices.length;
- packedData[count++] = indicesLength;
- for (var x = 0; x < indicesLength; x++) {
- var index = indices[x];
- packedData[count++] = index.count;
- packedData[count++] = index.offset;
- var tableIndex = attributeTable.indexOf(index.attribute);
- if (tableIndex === -1) {
- tableIndex = attributeTable.length;
- attributeTable.push(index.attribute);
- }
- packedData[count++] = tableIndex;
- }
- packedData[count++] = property.value.length;
- packedData.set(property.value, count);
- count += property.value.length;
- }
- }
- transferableObjects.push(packedData.buffer);
- return {
- stringTable : stringTable,
- packedData : packedData,
- attributeTable : attributeTable
- };
- }
- function unpackAttributeLocations(packedAttributeLocations, vaAttributes) {
- var stringTable = packedAttributeLocations.stringTable;
- var attributeTable = packedAttributeLocations.attributeTable;
- var packedData = packedAttributeLocations.packedData;
- var attributeLocations = new Array(packedData[0]);
- var attributeLocationsIndex = 0;
- var i = 1;
- var packedDataLength = packedData.length;
- while (i < packedDataLength) {
- var instance = {};
- var numAttributes = packedData[i++];
- for (var x = 0; x < numAttributes; x++) {
- var name = stringTable[packedData[i++]];
- var indices = new Array(packedData[i++]);
- for (var indicesIndex = 0; indicesIndex < indices.length; indicesIndex++) {
- var index = {};
- index.count = packedData[i++];
- index.offset = packedData[i++];
- index.attribute = attributeTable[packedData[i++]];
- indices[indicesIndex] = index;
- }
- var valueLength = packedData[i++];
- var value = ComponentDatatype.createTypedArray(indices[0].attribute.componentDatatype, valueLength);
- for (var valueIndex = 0; valueIndex < valueLength; valueIndex++) {
- value[valueIndex] = packedData[i++];
- }
- instance[name] = {
- dirty : false,
- indices : indices,
- value : value
- };
- }
- attributeLocations[attributeLocationsIndex++] = instance;
- }
- return attributeLocations;
- }
- /**
- * @private
- */
- PrimitivePipeline.packCombineGeometryParameters = function(parameters, transferableObjects) {
- var createGeometryResults = parameters.createGeometryResults;
- var length = createGeometryResults.length;
- for (var i = 0; i < length; i++) {
- transferableObjects.push(createGeometryResults[i].packedData.buffer);
- }
- var packedPickIds;
- if (parameters.allowPicking) {
- packedPickIds = packPickIds(parameters.pickIds, transferableObjects);
- }
- return {
- createGeometryResults : parameters.createGeometryResults,
- packedInstances : packInstancesForCombine(parameters.instances, transferableObjects),
- packedPickIds : packedPickIds,
- ellipsoid : parameters.ellipsoid,
- isGeographic : parameters.projection instanceof GeographicProjection,
- elementIndexUintSupported : parameters.elementIndexUintSupported,
- scene3DOnly : parameters.scene3DOnly,
- allowPicking : parameters.allowPicking,
- vertexCacheOptimize : parameters.vertexCacheOptimize,
- compressVertices : parameters.compressVertices,
- modelMatrix : parameters.modelMatrix
- };
- };
- /**
- * @private
- */
- PrimitivePipeline.unpackCombineGeometryParameters = function(packedParameters) {
- var instances = unpackInstancesForCombine(packedParameters.packedInstances);
- var pickIds = packedParameters.allowPicking ? unpackPickIds(packedParameters.packedPickIds) : undefined;
- var createGeometryResults = packedParameters.createGeometryResults;
- var length = createGeometryResults.length;
- var instanceIndex = 0;
- for (var resultIndex = 0; resultIndex < length; resultIndex++) {
- var geometries = PrimitivePipeline.unpackCreateGeometryResults(createGeometryResults[resultIndex]);
- var geometriesLength = geometries.length;
- for (var geometryIndex = 0; geometryIndex < geometriesLength; geometryIndex++) {
- instances[instanceIndex++].geometry = geometries[geometryIndex];
- }
- }
- var ellipsoid = Ellipsoid.clone(packedParameters.ellipsoid);
- var projection = packedParameters.isGeographic ? new GeographicProjection(ellipsoid) : new WebMercatorProjection(ellipsoid);
- return {
- instances : instances,
- pickIds : pickIds,
- ellipsoid : ellipsoid,
- projection : projection,
- elementIndexUintSupported : packedParameters.elementIndexUintSupported,
- scene3DOnly : packedParameters.scene3DOnly,
- allowPicking : packedParameters.allowPicking,
- vertexCacheOptimize : packedParameters.vertexCacheOptimize,
- compressVertices : packedParameters.compressVertices,
- modelMatrix : Matrix4.clone(packedParameters.modelMatrix)
- };
- };
- /**
- * @private
- */
- PrimitivePipeline.packCombineGeometryResults = function(results, transferableObjects) {
- transferGeometries(results.geometries, transferableObjects);
- transferPerInstanceAttributes(results.vaAttributes, transferableObjects);
- return {
- geometries : results.geometries,
- attributeLocations : results.attributeLocations,
- vaAttributes : results.vaAttributes,
- packedVaAttributeLocations : packAttributeLocations(results.vaAttributeLocations, transferableObjects),
- modelMatrix : results.modelMatrix
- };
- };
- /**
- * @private
- */
- PrimitivePipeline.unpackCombineGeometryResults = function(packedResult) {
- return {
- geometries : packedResult.geometries,
- attributeLocations : packedResult.attributeLocations,
- vaAttributes : packedResult.vaAttributes,
- perInstanceAttributeLocations : unpackAttributeLocations(packedResult.packedVaAttributeLocations, packedResult.vaAttributes),
- modelMatrix : packedResult.modelMatrix
- };
- };
- return PrimitivePipeline;
- });
|