12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040 |
- define(['./createTaskProcessorWorker', './defaultValue-fe22d8c0', './WebMercatorProjection-13ed1a6e', './Matrix3-41c58dde', './Math-0a2ac845', './Check-6ede7e26'], (function (createTaskProcessorWorker, defaultValue, WebMercatorProjection, Matrix3, Math$1, Check) { 'use strict';
- /* global require */
- let draco;
- function bilinearInterpolate(tx, ty, h00, h10, h01, h11) {
- const a = h00 * (1 - tx) + h10 * tx;
- const b = h01 * (1 - tx) + h11 * tx;
- return a * (1 - ty) + b * ty;
- }
- function sampleMap(u, v, width, data) {
- const address = u + v * width;
- return data[address];
- }
- function sampleGeoid(sampleX, sampleY, geoidData) {
- const extent = geoidData.nativeExtent;
- let x =
- ((sampleX - extent.west) / (extent.east - extent.west)) *
- (geoidData.width - 1);
- let y =
- ((sampleY - extent.south) / (extent.north - extent.south)) *
- (geoidData.height - 1);
- const xi = Math.floor(x);
- let yi = Math.floor(y);
- x -= xi;
- y -= yi;
- const xNext = xi < geoidData.width ? xi + 1 : xi;
- let yNext = yi < geoidData.height ? yi + 1 : yi;
- yi = geoidData.height - 1 - yi;
- yNext = geoidData.height - 1 - yNext;
- const h00 = sampleMap(xi, yi, geoidData.width, geoidData.buffer);
- const h10 = sampleMap(xNext, yi, geoidData.width, geoidData.buffer);
- const h01 = sampleMap(xi, yNext, geoidData.width, geoidData.buffer);
- const h11 = sampleMap(xNext, yNext, geoidData.width, geoidData.buffer);
- let finalHeight = bilinearInterpolate(x, y, h00, h10, h01, h11);
- finalHeight = finalHeight * geoidData.scale + geoidData.offset;
- return finalHeight;
- }
- function sampleGeoidFromList(lon, lat, geoidDataList) {
- for (let i = 0; i < geoidDataList.length; i++) {
- const localExtent = geoidDataList[i].nativeExtent;
- let localPt = new Matrix3.Cartesian3();
- if (geoidDataList[i].projectionType === "WebMercator") {
- const radii = geoidDataList[i].projection._ellipsoid._radii;
- const webMercatorProj = new WebMercatorProjection.WebMercatorProjection(
- new Matrix3.Ellipsoid(radii.x, radii.y, radii.z)
- );
- localPt = webMercatorProj.project(new Matrix3.Cartographic(lon, lat, 0));
- } else {
- localPt.x = lon;
- localPt.y = lat;
- }
- if (
- localPt.x > localExtent.west &&
- localPt.x < localExtent.east &&
- localPt.y > localExtent.south &&
- localPt.y < localExtent.north
- ) {
- return sampleGeoid(localPt.x, localPt.y, geoidDataList[i]);
- }
- }
- return 0;
- }
- function orthometricToEllipsoidal(
- vertexCount,
- position,
- scale_x,
- scale_y,
- center,
- geoidDataList,
- fast
- ) {
- if (fast) {
- // Geometry is already relative to the tile origin which has already been shifted to account for geoid height
- // Nothing to do here
- return;
- }
- // For more precision, sample the geoid height at each vertex and shift by the difference between that value and the height at the center of the tile
- const centerHeight = sampleGeoidFromList(
- center.longitude,
- center.latitude,
- geoidDataList
- );
- for (let i = 0; i < vertexCount; ++i) {
- const height = sampleGeoidFromList(
- center.longitude + Math$1.CesiumMath.toRadians(scale_x * position[i * 3]),
- center.latitude + Math$1.CesiumMath.toRadians(scale_y * position[i * 3 + 1]),
- geoidDataList
- );
- position[i * 3 + 2] += height - centerHeight;
- }
- }
- function transformToLocal(
- vertexCount,
- positions,
- normals,
- cartographicCenter,
- cartesianCenter,
- parentRotation,
- ellipsoidRadiiSquare,
- scale_x,
- scale_y
- ) {
- if (vertexCount === 0 || !defaultValue.defined(positions) || positions.length === 0) {
- return;
- }
- const ellipsoid = new Matrix3.Ellipsoid(
- Math.sqrt(ellipsoidRadiiSquare.x),
- Math.sqrt(ellipsoidRadiiSquare.y),
- Math.sqrt(ellipsoidRadiiSquare.z)
- );
- for (let i = 0; i < vertexCount; ++i) {
- const indexOffset = i * 3;
- const indexOffset1 = indexOffset + 1;
- const indexOffset2 = indexOffset + 2;
- const cartographic = new Matrix3.Cartographic();
- cartographic.longitude =
- cartographicCenter.longitude +
- Math$1.CesiumMath.toRadians(scale_x * positions[indexOffset]);
- cartographic.latitude =
- cartographicCenter.latitude +
- Math$1.CesiumMath.toRadians(scale_y * positions[indexOffset1]);
- cartographic.height = cartographicCenter.height + positions[indexOffset2];
- const position = {};
- ellipsoid.cartographicToCartesian(cartographic, position);
- position.x -= cartesianCenter.x;
- position.y -= cartesianCenter.y;
- position.z -= cartesianCenter.z;
- const rotatedPosition = {};
- Matrix3.Matrix3.multiplyByVector(parentRotation, position, rotatedPosition);
- positions[indexOffset] = rotatedPosition.x;
- positions[indexOffset1] = rotatedPosition.y;
- positions[indexOffset2] = rotatedPosition.z;
- if (defaultValue.defined(normals)) {
- const normal = new Matrix3.Cartesian3(
- normals[indexOffset],
- normals[indexOffset1],
- normals[indexOffset2]
- );
- const rotatedNormal = {};
- Matrix3.Matrix3.multiplyByVector(parentRotation, normal, rotatedNormal);
- // TODO: check if normals are Z-UP or Y-UP and flip y and z
- normals[indexOffset] = rotatedNormal.x;
- normals[indexOffset1] = rotatedNormal.y;
- normals[indexOffset2] = rotatedNormal.z;
- }
- }
- }
- function cropUVs(vertexCount, uv0s, uvRegions) {
- for (let vertexIndex = 0; vertexIndex < vertexCount; ++vertexIndex) {
- const minU = uvRegions[vertexIndex * 4] / 65535.0;
- const minV = uvRegions[vertexIndex * 4 + 1] / 65535.0;
- const scaleU =
- (uvRegions[vertexIndex * 4 + 2] - uvRegions[vertexIndex * 4]) / 65535.0;
- const scaleV =
- (uvRegions[vertexIndex * 4 + 3] - uvRegions[vertexIndex * 4 + 1]) /
- 65535.0;
- uv0s[vertexIndex * 2] *= scaleU;
- uv0s[vertexIndex * 2] += minU;
- uv0s[vertexIndex * 2 + 1] *= scaleV;
- uv0s[vertexIndex * 2 + 1] += minV;
- }
- }
- function generateGltfBuffer(
- vertexCount,
- indices,
- positions,
- normals,
- uv0s,
- colors
- ) {
- if (vertexCount === 0 || !defaultValue.defined(positions) || positions.length === 0) {
- return {
- buffers: [],
- bufferViews: [],
- accessors: [],
- meshes: [],
- nodes: [],
- nodesInScene: [],
- };
- }
- const buffers = [];
- const bufferViews = [];
- const accessors = [];
- const meshes = [];
- const nodes = [];
- const nodesInScene = [];
- // If we provide indices, then the vertex count is the length
- // of that array, otherwise we assume non-indexed triangle
- if (defaultValue.defined(indices)) {
- vertexCount = indices.length;
- }
- // Allocate array
- const indexArray = new Uint32Array(vertexCount);
- if (defaultValue.defined(indices)) {
- // Set the indices
- for (let vertexIndex = 0; vertexIndex < vertexCount; ++vertexIndex) {
- indexArray[vertexIndex] = indices[vertexIndex];
- }
- } else {
- // Generate indices
- for (
- let newVertexIndex = 0;
- newVertexIndex < vertexCount;
- ++newVertexIndex
- ) {
- indexArray[newVertexIndex] = newVertexIndex;
- }
- }
- // Push to the buffers, bufferViews and accessors
- const indicesBlob = new Blob([indexArray], { type: "application/binary" });
- const indicesURL = URL.createObjectURL(indicesBlob);
- const endIndex = vertexCount;
- // POSITIONS
- const meshPositions = positions.subarray(0, endIndex * 3);
- const positionsBlob = new Blob([meshPositions], {
- type: "application/binary",
- });
- const positionsURL = URL.createObjectURL(positionsBlob);
- let minX = Number.POSITIVE_INFINITY;
- let maxX = Number.NEGATIVE_INFINITY;
- let minY = Number.POSITIVE_INFINITY;
- let maxY = Number.NEGATIVE_INFINITY;
- let minZ = Number.POSITIVE_INFINITY;
- let maxZ = Number.NEGATIVE_INFINITY;
- for (let i = 0; i < meshPositions.length / 3; i++) {
- minX = Math.min(minX, meshPositions[i * 3 + 0]);
- maxX = Math.max(maxX, meshPositions[i * 3 + 0]);
- minY = Math.min(minY, meshPositions[i * 3 + 1]);
- maxY = Math.max(maxY, meshPositions[i * 3 + 1]);
- minZ = Math.min(minZ, meshPositions[i * 3 + 2]);
- maxZ = Math.max(maxZ, meshPositions[i * 3 + 2]);
- }
- // NORMALS
- const meshNormals = normals ? normals.subarray(0, endIndex * 3) : undefined;
- let normalsURL;
- if (defaultValue.defined(meshNormals)) {
- const normalsBlob = new Blob([meshNormals], {
- type: "application/binary",
- });
- normalsURL = URL.createObjectURL(normalsBlob);
- }
- // UV0s
- const meshUv0s = uv0s ? uv0s.subarray(0, endIndex * 2) : undefined;
- let uv0URL;
- if (defaultValue.defined(meshUv0s)) {
- const uv0Blob = new Blob([meshUv0s], { type: "application/binary" });
- uv0URL = URL.createObjectURL(uv0Blob);
- }
- // COLORS
- const meshColorsInBytes = defaultValue.defined(colors)
- ? colors.subarray(0, endIndex * 4)
- : undefined;
- let colorsURL;
- if (defaultValue.defined(meshColorsInBytes)) {
- const colorsBlob = new Blob([meshColorsInBytes], {
- type: "application/binary",
- });
- colorsURL = URL.createObjectURL(colorsBlob);
- }
- const posIndex = 0;
- let normalIndex = 0;
- let uv0Index = 0;
- let colorIndex = 0;
- let indicesIndex = 0;
- let currentIndex = posIndex;
- const attributes = {};
- // POSITIONS
- attributes.POSITION = posIndex;
- buffers.push({
- uri: positionsURL,
- byteLength: meshPositions.byteLength,
- });
- bufferViews.push({
- buffer: posIndex,
- byteOffset: 0,
- byteLength: meshPositions.byteLength,
- target: 34962,
- });
- accessors.push({
- bufferView: posIndex,
- byteOffset: 0,
- componentType: 5126,
- count: vertexCount,
- type: "VEC3",
- max: [minX, minY, minZ],
- min: [maxX, maxY, maxZ],
- });
- // NORMALS
- if (defaultValue.defined(normalsURL)) {
- ++currentIndex;
- normalIndex = currentIndex;
- attributes.NORMAL = normalIndex;
- buffers.push({
- uri: normalsURL,
- byteLength: meshNormals.byteLength,
- });
- bufferViews.push({
- buffer: normalIndex,
- byteOffset: 0,
- byteLength: meshNormals.byteLength,
- target: 34962,
- });
- accessors.push({
- bufferView: normalIndex,
- byteOffset: 0,
- componentType: 5126,
- count: vertexCount,
- type: "VEC3",
- });
- }
- // UV0
- if (defaultValue.defined(uv0URL)) {
- ++currentIndex;
- uv0Index = currentIndex;
- attributes.TEXCOORD_0 = uv0Index;
- buffers.push({
- uri: uv0URL,
- byteLength: meshUv0s.byteLength,
- });
- bufferViews.push({
- buffer: uv0Index,
- byteOffset: 0,
- byteLength: meshUv0s.byteLength,
- target: 34962,
- });
- accessors.push({
- bufferView: uv0Index,
- byteOffset: 0,
- componentType: 5126,
- count: vertexCount,
- type: "VEC2",
- });
- }
- // COLORS
- if (defaultValue.defined(colorsURL)) {
- ++currentIndex;
- colorIndex = currentIndex;
- attributes.COLOR_0 = colorIndex;
- buffers.push({
- uri: colorsURL,
- byteLength: meshColorsInBytes.byteLength,
- });
- bufferViews.push({
- buffer: colorIndex,
- byteOffset: 0,
- byteLength: meshColorsInBytes.byteLength,
- target: 34962,
- });
- accessors.push({
- bufferView: colorIndex,
- byteOffset: 0,
- componentType: 5121,
- normalized: true,
- count: vertexCount,
- type: "VEC4",
- });
- }
- // INDICES
- ++currentIndex;
- indicesIndex = currentIndex;
- buffers.push({
- uri: indicesURL,
- byteLength: indexArray.byteLength,
- });
- bufferViews.push({
- buffer: indicesIndex,
- byteOffset: 0,
- byteLength: indexArray.byteLength,
- target: 34963,
- });
- accessors.push({
- bufferView: indicesIndex,
- byteOffset: 0,
- componentType: 5125,
- count: vertexCount,
- type: "SCALAR",
- });
- // Create a new mesh for this page
- meshes.push({
- primitives: [
- {
- attributes: attributes,
- indices: indicesIndex,
- material: 0,
- },
- ],
- });
- nodesInScene.push(0);
- nodes.push({ mesh: 0 });
- return {
- buffers: buffers,
- bufferViews: bufferViews,
- accessors: accessors,
- meshes: meshes,
- nodes: nodes,
- nodesInScene: nodesInScene,
- };
- }
- function decode(data, schema, bufferInfo, featureData) {
- const magicNumber = new Uint8Array(data, 0, 5);
- if (
- magicNumber[0] === "D".charCodeAt() &&
- magicNumber[1] === "R".charCodeAt() &&
- magicNumber[2] === "A".charCodeAt() &&
- magicNumber[3] === "C".charCodeAt() &&
- magicNumber[4] === "O".charCodeAt()
- ) {
- return decodeDracoEncodedGeometry(data);
- }
- return decodeBinaryGeometry(data, schema, bufferInfo, featureData);
- }
- function decodeDracoEncodedGeometry(data) {
- // Create the Draco decoder.
- const dracoDecoderModule = draco;
- const buffer = new dracoDecoderModule.DecoderBuffer();
- const byteArray = new Uint8Array(data);
- buffer.Init(byteArray, byteArray.length);
- // Create a buffer to hold the encoded data.
- const dracoDecoder = new dracoDecoderModule.Decoder();
- const geometryType = dracoDecoder.GetEncodedGeometryType(buffer);
- const metadataQuerier = new dracoDecoderModule.MetadataQuerier();
- // Decode the encoded geometry.
- // See: https://github.com/google/draco/blob/master/src/draco/javascript/emscripten/draco_web_decoder.idl
- let dracoGeometry;
- let status;
- if (geometryType === dracoDecoderModule.TRIANGULAR_MESH) {
- dracoGeometry = new dracoDecoderModule.Mesh();
- status = dracoDecoder.DecodeBufferToMesh(buffer, dracoGeometry);
- }
- const decodedGeometry = {
- vertexCount: [0],
- featureCount: 0,
- };
- // if all is OK
- if (defaultValue.defined(status) && status.ok() && dracoGeometry.ptr !== 0) {
- const faceCount = dracoGeometry.num_faces();
- const attributesCount = dracoGeometry.num_attributes();
- const vertexCount = dracoGeometry.num_points();
- decodedGeometry.indices = new Uint32Array(faceCount * 3);
- const faces = decodedGeometry.indices;
- decodedGeometry.vertexCount[0] = vertexCount;
- decodedGeometry.scale_x = 1;
- decodedGeometry.scale_y = 1;
- // Decode faces
- // @TODO: Replace that code with GetTrianglesUInt32Array for better efficiency
- const face = new dracoDecoderModule.DracoInt32Array(3);
- for (let faceIndex = 0; faceIndex < faceCount; ++faceIndex) {
- dracoDecoder.GetFaceFromMesh(dracoGeometry, faceIndex, face);
- faces[faceIndex * 3] = face.GetValue(0);
- faces[faceIndex * 3 + 1] = face.GetValue(1);
- faces[faceIndex * 3 + 2] = face.GetValue(2);
- }
- dracoDecoderModule.destroy(face);
- for (let attrIndex = 0; attrIndex < attributesCount; ++attrIndex) {
- const dracoAttribute = dracoDecoder.GetAttribute(
- dracoGeometry,
- attrIndex
- );
- const attributeData = decodeDracoAttribute(
- dracoDecoderModule,
- dracoDecoder,
- dracoGeometry,
- dracoAttribute,
- vertexCount
- );
- // initial mapping
- const dracoAttributeType = dracoAttribute.attribute_type();
- let attributei3sName = "unknown";
- if (dracoAttributeType === dracoDecoderModule.POSITION) {
- attributei3sName = "positions";
- } else if (dracoAttributeType === dracoDecoderModule.NORMAL) {
- attributei3sName = "normals";
- } else if (dracoAttributeType === dracoDecoderModule.COLOR) {
- attributei3sName = "colors";
- } else if (dracoAttributeType === dracoDecoderModule.TEX_COORD) {
- attributei3sName = "uv0s";
- }
- // get the metadata
- const metadata = dracoDecoder.GetAttributeMetadata(
- dracoGeometry,
- attrIndex
- );
- if (metadata.ptr !== 0) {
- const numEntries = metadataQuerier.NumEntries(metadata);
- for (let entry = 0; entry < numEntries; ++entry) {
- const entryName = metadataQuerier.GetEntryName(metadata, entry);
- if (entryName === "i3s-scale_x") {
- decodedGeometry.scale_x = metadataQuerier.GetDoubleEntry(
- metadata,
- "i3s-scale_x"
- );
- } else if (entryName === "i3s-scale_y") {
- decodedGeometry.scale_y = metadataQuerier.GetDoubleEntry(
- metadata,
- "i3s-scale_y"
- );
- } else if (entryName === "i3s-attribute-type") {
- attributei3sName = metadataQuerier.GetStringEntry(
- metadata,
- "i3s-attribute-type"
- );
- }
- }
- }
- if (defaultValue.defined(decodedGeometry[attributei3sName])) {
- console.log("Attribute already exists", attributei3sName);
- }
- decodedGeometry[attributei3sName] = attributeData;
- if (attributei3sName === "feature-index") {
- decodedGeometry.featureCount++;
- }
- }
- dracoDecoderModule.destroy(dracoGeometry);
- }
- dracoDecoderModule.destroy(metadataQuerier);
- dracoDecoderModule.destroy(dracoDecoder);
- return decodedGeometry;
- }
- function decodeDracoAttribute(
- dracoDecoderModule,
- dracoDecoder,
- dracoGeometry,
- dracoAttribute,
- vertexCount
- ) {
- const bufferSize = dracoAttribute.num_components() * vertexCount;
- let dracoAttributeData;
- const handlers = [
- function () {}, // DT_INVALID - 0
- function () {
- // DT_INT8 - 1
- dracoAttributeData = new dracoDecoderModule.DracoInt8Array(bufferSize);
- const success = dracoDecoder.GetAttributeInt8ForAllPoints(
- dracoGeometry,
- dracoAttribute,
- dracoAttributeData
- );
- if (!success) {
- console.error("Bad stream");
- }
- const attributeData = new Int8Array(bufferSize);
- for (let i = 0; i < bufferSize; ++i) {
- attributeData[i] = dracoAttributeData.GetValue(i);
- }
- return attributeData;
- },
- function () {
- // DT_UINT8 - 2
- dracoAttributeData = new dracoDecoderModule.DracoInt8Array(bufferSize);
- const success = dracoDecoder.GetAttributeUInt8ForAllPoints(
- dracoGeometry,
- dracoAttribute,
- dracoAttributeData
- );
- if (!success) {
- console.error("Bad stream");
- }
- const attributeData = new Uint8Array(bufferSize);
- for (let i = 0; i < bufferSize; ++i) {
- attributeData[i] = dracoAttributeData.GetValue(i);
- }
- return attributeData;
- },
- function () {
- // DT_INT16 - 3
- dracoAttributeData = new dracoDecoderModule.DracoInt16Array(bufferSize);
- const success = dracoDecoder.GetAttributeInt16ForAllPoints(
- dracoGeometry,
- dracoAttribute,
- dracoAttributeData
- );
- if (!success) {
- console.error("Bad stream");
- }
- const attributeData = new Int16Array(bufferSize);
- for (let i = 0; i < bufferSize; ++i) {
- attributeData[i] = dracoAttributeData.GetValue(i);
- }
- return attributeData;
- },
- function () {
- // DT_UINT16 - 4
- dracoAttributeData = new dracoDecoderModule.DracoInt16Array(bufferSize);
- const success = dracoDecoder.GetAttributeUInt16ForAllPoints(
- dracoGeometry,
- dracoAttribute,
- dracoAttributeData
- );
- if (!success) {
- console.error("Bad stream");
- }
- const attributeData = new Uint16Array(bufferSize);
- for (let i = 0; i < bufferSize; ++i) {
- attributeData[i] = dracoAttributeData.GetValue(i);
- }
- return attributeData;
- },
- function () {
- // DT_INT32 - 5
- dracoAttributeData = new dracoDecoderModule.DracoInt32Array(bufferSize);
- const success = dracoDecoder.GetAttributeInt32ForAllPoints(
- dracoGeometry,
- dracoAttribute,
- dracoAttributeData
- );
- if (!success) {
- console.error("Bad stream");
- }
- const attributeData = new Int32Array(bufferSize);
- for (let i = 0; i < bufferSize; ++i) {
- attributeData[i] = dracoAttributeData.GetValue(i);
- }
- return attributeData;
- },
- function () {
- // DT_UINT32 - 6
- dracoAttributeData = new dracoDecoderModule.DracoInt32Array(bufferSize);
- const success = dracoDecoder.GetAttributeUInt32ForAllPoints(
- dracoGeometry,
- dracoAttribute,
- dracoAttributeData
- );
- if (!success) {
- console.error("Bad stream");
- }
- const attributeData = new Uint32Array(bufferSize);
- for (let i = 0; i < bufferSize; ++i) {
- attributeData[i] = dracoAttributeData.GetValue(i);
- }
- return attributeData;
- },
- function () {
- // DT_INT64 - 7
- },
- function () {
- // DT_UINT64 - 8
- },
- function () {
- // DT_FLOAT32 - 9
- dracoAttributeData = new dracoDecoderModule.DracoFloat32Array(bufferSize);
- const success = dracoDecoder.GetAttributeFloatForAllPoints(
- dracoGeometry,
- dracoAttribute,
- dracoAttributeData
- );
- if (!success) {
- console.error("Bad stream");
- }
- const attributeData = new Float32Array(bufferSize);
- for (let i = 0; i < bufferSize; ++i) {
- attributeData[i] = dracoAttributeData.GetValue(i);
- }
- return attributeData;
- },
- function () {
- // DT_FLOAT64 - 10
- },
- function () {
- // DT_FLOAT32 - 11
- dracoAttributeData = new dracoDecoderModule.DracoUInt8Array(bufferSize);
- const success = dracoDecoder.GetAttributeUInt8ForAllPoints(
- dracoGeometry,
- dracoAttribute,
- dracoAttributeData
- );
- if (!success) {
- console.error("Bad stream");
- }
- const attributeData = new Uint8Array(bufferSize);
- for (let i = 0; i < bufferSize; ++i) {
- attributeData[i] = dracoAttributeData.GetValue(i);
- }
- return attributeData;
- },
- ];
- const attributeData = handlers[dracoAttribute.data_type()]();
- if (defaultValue.defined(dracoAttributeData)) {
- dracoDecoderModule.destroy(dracoAttributeData);
- }
- return attributeData;
- }
- const binaryAttributeDecoders = {
- position: function (decodedGeometry, data, offset) {
- const count = decodedGeometry.vertexCount * 3;
- decodedGeometry.positions = new Float32Array(data, offset, count);
- offset += count * 4;
- return offset;
- },
- normal: function (decodedGeometry, data, offset) {
- const count = decodedGeometry.vertexCount * 3;
- decodedGeometry.normals = new Float32Array(data, offset, count);
- offset += count * 4;
- return offset;
- },
- uv0: function (decodedGeometry, data, offset) {
- const count = decodedGeometry.vertexCount * 2;
- decodedGeometry.uv0s = new Float32Array(data, offset, count);
- offset += count * 4;
- return offset;
- },
- color: function (decodedGeometry, data, offset) {
- const count = decodedGeometry.vertexCount * 4;
- decodedGeometry.colors = new Uint8Array(data, offset, count);
- offset += count;
- return offset;
- },
- featureId: function (decodedGeometry, data, offset) {
- // We don't need to use this for anything so just increment the offset
- const count = decodedGeometry.featureCount;
- offset += count * 8;
- return offset;
- },
- id: function (decodedGeometry, data, offset) {
- // We don't need to use this for anything so just increment the offset
- const count = decodedGeometry.featureCount;
- offset += count * 8;
- return offset;
- },
- faceRange: function (decodedGeometry, data, offset) {
- const count = decodedGeometry.featureCount * 2;
- decodedGeometry.faceRange = new Uint32Array(data, offset, count);
- offset += count * 4;
- return offset;
- },
- uvRegion: function (decodedGeometry, data, offset) {
- const count = decodedGeometry.vertexCount * 4;
- decodedGeometry["uv-region"] = new Uint16Array(data, offset, count);
- offset += count * 2;
- return offset;
- },
- region: function (decodedGeometry, data, offset) {
- const count = decodedGeometry.vertexCount * 4;
- decodedGeometry["uv-region"] = new Uint16Array(data, offset, count);
- offset += count * 2;
- return offset;
- },
- };
- function decodeBinaryGeometry(data, schema, bufferInfo, featureData) {
- // From this spec:
- // https://github.com/Esri/i3s-spec/blob/master/docs/1.7/defaultGeometrySchema.cmn.md
- const decodedGeometry = {
- vertexCount: 0,
- };
- const dataView = new DataView(data);
- try {
- let offset = 0;
- decodedGeometry.vertexCount = dataView.getUint32(offset, 1);
- offset += 4;
- decodedGeometry.featureCount = dataView.getUint32(offset, 1);
- offset += 4;
- if (defaultValue.defined(bufferInfo)) {
- for (
- let attrIndex = 0;
- attrIndex < bufferInfo.attributes.length;
- attrIndex++
- ) {
- if (
- defaultValue.defined(binaryAttributeDecoders[bufferInfo.attributes[attrIndex]])
- ) {
- offset = binaryAttributeDecoders[bufferInfo.attributes[attrIndex]](
- decodedGeometry,
- data,
- offset
- );
- } else {
- console.error(
- "Unknown decoder for",
- bufferInfo.attributes[attrIndex]
- );
- }
- }
- } else {
- let ordering = schema.ordering;
- let featureAttributeOrder = schema.featureAttributeOrder;
- if (
- defaultValue.defined(featureData) &&
- defaultValue.defined(featureData.geometryData) &&
- defaultValue.defined(featureData.geometryData[0]) &&
- defaultValue.defined(featureData.geometryData[0].params)
- ) {
- ordering = Object.keys(
- featureData.geometryData[0].params.vertexAttributes
- );
- featureAttributeOrder = Object.keys(
- featureData.geometryData[0].params.featureAttributes
- );
- }
- // Use default geometry schema
- for (let i = 0; i < ordering.length; i++) {
- const decoder = binaryAttributeDecoders[ordering[i]];
- if (!defaultValue.defined(decoder)) {
- console.log(ordering[i]);
- }
- offset = decoder(decodedGeometry, data, offset);
- }
- for (let j = 0; j < featureAttributeOrder.length; j++) {
- const curDecoder = binaryAttributeDecoders[featureAttributeOrder[j]];
- if (!defaultValue.defined(curDecoder)) {
- console.log(featureAttributeOrder[j]);
- }
- offset = curDecoder(decodedGeometry, data, offset);
- }
- }
- } catch (e) {
- console.error(e);
- }
- decodedGeometry.scale_x = 1;
- decodedGeometry.scale_y = 1;
- return decodedGeometry;
- }
- function decodeI3S(parameters) {
- // Decode the data into geometry
- const geometryData = decode(
- parameters.binaryData,
- parameters.schema,
- parameters.bufferInfo,
- parameters.featureData
- );
- // Adjust height from orthometric to ellipsoidal
- if (
- defaultValue.defined(parameters.geoidDataList) &&
- parameters.geoidDataList.length > 0
- ) {
- orthometricToEllipsoidal(
- geometryData.vertexCount,
- geometryData.positions,
- geometryData.scale_x,
- geometryData.scale_y,
- parameters.cartographicCenter,
- parameters.geoidDataList,
- false
- );
- }
- // Transform vertices to local
- transformToLocal(
- geometryData.vertexCount,
- geometryData.positions,
- geometryData.normals,
- parameters.cartographicCenter,
- parameters.cartesianCenter,
- parameters.parentRotation,
- parameters.ellipsoidRadiiSquare,
- geometryData.scale_x,
- geometryData.scale_y
- );
- // Adjust UVs if there is a UV region
- if (defaultValue.defined(geometryData.uv0s) && defaultValue.defined(geometryData["uv-region"])) {
- cropUVs(
- geometryData.vertexCount,
- geometryData.uv0s,
- geometryData["uv-region"]
- );
- }
- // Create the final buffer
- const meshData = generateGltfBuffer(
- geometryData.vertexCount,
- geometryData.indices,
- geometryData.positions,
- geometryData.normals,
- geometryData.uv0s,
- geometryData.colors
- );
- const customAttributes = {};
- if (defaultValue.defined(geometryData["feature-index"])) {
- customAttributes.positions = geometryData.positions;
- customAttributes.indices = geometryData.indices;
- customAttributes.featureIndex = geometryData["feature-index"];
- customAttributes.cartesianCenter = parameters.cartesianCenter;
- customAttributes.parentRotation = parameters.parentRotation;
- } else if (defaultValue.defined(geometryData["faceRange"])) {
- customAttributes.positions = geometryData.positions;
- customAttributes.indices = geometryData.indices;
- customAttributes.sourceURL = parameters.url;
- customAttributes.cartesianCenter = parameters.cartesianCenter;
- customAttributes.parentRotation = parameters.parentRotation;
- // Build the feature index array from the faceRange.
- customAttributes.featureIndex = new Array(geometryData.positions.length);
- for (
- let range = 0;
- range < geometryData["faceRange"].length - 1;
- range += 2
- ) {
- const curIndex = range / 2;
- const rangeStart = geometryData["faceRange"][range];
- const rangeEnd = geometryData["faceRange"][range + 1];
- for (let i = rangeStart; i <= rangeEnd; i++) {
- customAttributes.featureIndex[i * 3] = curIndex;
- customAttributes.featureIndex[i * 3 + 1] = curIndex;
- customAttributes.featureIndex[i * 3 + 2] = curIndex;
- }
- }
- }
- meshData._customAttributes = customAttributes;
- const results = {
- meshData: meshData,
- };
- return results;
- }
- function initWorker(dracoModule) {
- draco = dracoModule;
- self.onmessage = createTaskProcessorWorker(decodeI3S);
- self.postMessage(true);
- }
- function decodeI3SStart(event) {
- const data = event.data;
- // Expect the first message to be to load a web assembly module
- const wasmConfig = data.webAssemblyConfig;
- if (defaultValue.defined(wasmConfig)) {
- // Require and compile WebAssembly module, or use fallback if not supported
- return require([wasmConfig.modulePath], function (dracoModule) {
- if (defaultValue.defined(wasmConfig.wasmBinaryFile)) {
- if (!defaultValue.defined(dracoModule)) {
- dracoModule = self.DracoDecoderModule;
- }
- dracoModule(wasmConfig).then(function (compiledModule) {
- initWorker(compiledModule);
- });
- } else {
- initWorker(dracoModule());
- }
- });
- }
- }
- return decodeI3SStart;
- }));
|