/*global define*/ define([ '../Core/AttributeCompression', '../Core/Cartesian2', '../Core/Cartesian3', '../Core/Cartographic', '../Core/defined', '../Core/Ellipsoid', '../Core/IndexDatatype', '../Core/Math', './createTaskProcessorWorker' ], function( AttributeCompression, Cartesian2, Cartesian3, Cartographic, defined, Ellipsoid, IndexDatatype, CesiumMath, createTaskProcessorWorker) { "use strict"; var maxShort = 32767; var xIndex = 0; var yIndex = 1; var zIndex = 2; var hIndex = 3; var uIndex = 4; var vIndex = 5; var nIndex = 6; var cartesian3Scratch = new Cartesian3(); var cartographicScratch = new Cartographic(); var toPack = new Cartesian2(); function createVerticesFromQuantizedTerrainMesh(parameters, transferableObjects) { var quantizedVertices = parameters.quantizedVertices; var quantizedVertexCount = quantizedVertices.length / 3; var octEncodedNormals = parameters.octEncodedNormals; var edgeVertexCount = parameters.westIndices.length + parameters.eastIndices.length + parameters.southIndices.length + parameters.northIndices.length; var minimumHeight = parameters.minimumHeight; var maximumHeight = parameters.maximumHeight; var center = parameters.relativeToCenter; var rectangle = parameters.rectangle; var west = rectangle.west; var south = rectangle.south; var east = rectangle.east; var north = rectangle.north; var ellipsoid = Ellipsoid.clone(parameters.ellipsoid); var uBuffer = quantizedVertices.subarray(0, quantizedVertexCount); var vBuffer = quantizedVertices.subarray(quantizedVertexCount, 2 * quantizedVertexCount); var heightBuffer = quantizedVertices.subarray(quantizedVertexCount * 2, 3 * quantizedVertexCount); var hasVertexNormals = defined(octEncodedNormals); var vertexStride = 6; if (hasVertexNormals) { vertexStride += 1; } var vertexBuffer = new Float32Array(quantizedVertexCount * vertexStride + edgeVertexCount * vertexStride); for (var i = 0, bufferIndex = 0, n = 0; i < quantizedVertexCount; ++i, bufferIndex += vertexStride, n += 2) { var u = uBuffer[i] / maxShort; var v = vBuffer[i] / maxShort; var height = CesiumMath.lerp(minimumHeight, maximumHeight, heightBuffer[i] / maxShort); cartographicScratch.longitude = CesiumMath.lerp(west, east, u); cartographicScratch.latitude = CesiumMath.lerp(south, north, v); cartographicScratch.height = height; ellipsoid.cartographicToCartesian(cartographicScratch, cartesian3Scratch); vertexBuffer[bufferIndex + xIndex] = cartesian3Scratch.x - center.x; vertexBuffer[bufferIndex + yIndex] = cartesian3Scratch.y - center.y; vertexBuffer[bufferIndex + zIndex] = cartesian3Scratch.z - center.z; vertexBuffer[bufferIndex + hIndex] = height; vertexBuffer[bufferIndex + uIndex] = u; vertexBuffer[bufferIndex + vIndex] = v; if (hasVertexNormals) { toPack.x = octEncodedNormals[n]; toPack.y = octEncodedNormals[n + 1]; vertexBuffer[bufferIndex + nIndex] = AttributeCompression.octPackFloat(toPack); } } var edgeTriangleCount = Math.max(0, (edgeVertexCount - 4) * 2); var indexBufferLength = parameters.indices.length + edgeTriangleCount * 3; var indexBuffer = IndexDatatype.createTypedArray(quantizedVertexCount + edgeVertexCount, indexBufferLength); indexBuffer.set(parameters.indices, 0); // Add skirts. var vertexBufferIndex = quantizedVertexCount * vertexStride; var indexBufferIndex = parameters.indices.length; indexBufferIndex = addSkirt(vertexBuffer, vertexBufferIndex, indexBuffer, indexBufferIndex, parameters.westIndices, center, ellipsoid, rectangle, parameters.westSkirtHeight, true, hasVertexNormals); vertexBufferIndex += parameters.westIndices.length * vertexStride; indexBufferIndex = addSkirt(vertexBuffer, vertexBufferIndex, indexBuffer, indexBufferIndex, parameters.southIndices, center, ellipsoid, rectangle, parameters.southSkirtHeight, false, hasVertexNormals); vertexBufferIndex += parameters.southIndices.length * vertexStride; indexBufferIndex = addSkirt(vertexBuffer, vertexBufferIndex, indexBuffer, indexBufferIndex, parameters.eastIndices, center, ellipsoid, rectangle, parameters.eastSkirtHeight, false, hasVertexNormals); vertexBufferIndex += parameters.eastIndices.length * vertexStride; indexBufferIndex = addSkirt(vertexBuffer, vertexBufferIndex, indexBuffer, indexBufferIndex, parameters.northIndices, center, ellipsoid, rectangle, parameters.northSkirtHeight, true, hasVertexNormals); vertexBufferIndex += parameters.northIndices.length * vertexStride; transferableObjects.push(vertexBuffer.buffer, indexBuffer.buffer); return { vertices : vertexBuffer.buffer, indices : indexBuffer.buffer }; } function addSkirt(vertexBuffer, vertexBufferIndex, indexBuffer, indexBufferIndex, edgeVertices, center, ellipsoid, rectangle, skirtLength, isWestOrNorthEdge, hasVertexNormals) { var start, end, increment; var vertexStride = 6; if (hasVertexNormals) { vertexStride += 1; } if (isWestOrNorthEdge) { start = edgeVertices.length - 1; end = -1; increment = -1; } else { start = 0; end = edgeVertices.length; increment = 1; } var previousIndex = -1; var vertexIndex = vertexBufferIndex / vertexStride; var north = rectangle.north; var south = rectangle.south; var east = rectangle.east; var west = rectangle.west; if (east < west) { east += CesiumMath.TWO_PI; } for (var i = start; i !== end; i += increment) { var index = edgeVertices[i]; var offset = index * vertexStride; var u = vertexBuffer[offset + uIndex]; var v = vertexBuffer[offset + vIndex]; var h = vertexBuffer[offset + hIndex]; cartographicScratch.longitude = CesiumMath.lerp(west, east, u); cartographicScratch.latitude = CesiumMath.lerp(south, north, v); cartographicScratch.height = h - skirtLength; var position = ellipsoid.cartographicToCartesian(cartographicScratch, cartesian3Scratch); Cartesian3.subtract(position, center, position); vertexBuffer[vertexBufferIndex++] = position.x; vertexBuffer[vertexBufferIndex++] = position.y; vertexBuffer[vertexBufferIndex++] = position.z; vertexBuffer[vertexBufferIndex++] = cartographicScratch.height; vertexBuffer[vertexBufferIndex++] = u; vertexBuffer[vertexBufferIndex++] = v; if (hasVertexNormals) { vertexBuffer[vertexBufferIndex++] = vertexBuffer[offset + nIndex]; } if (previousIndex !== -1) { indexBuffer[indexBufferIndex++] = previousIndex; indexBuffer[indexBufferIndex++] = vertexIndex - 1; indexBuffer[indexBufferIndex++] = index; indexBuffer[indexBufferIndex++] = vertexIndex - 1; indexBuffer[indexBufferIndex++] = vertexIndex; indexBuffer[indexBufferIndex++] = index; } previousIndex = index; ++vertexIndex; } return indexBufferIndex; } return createTaskProcessorWorker(createVerticesFromQuantizedTerrainMesh); });