UNPKG

awv3

Version:
417 lines (370 loc) 19.7 kB
import { unpack, cross, applyMatrix, expand, distance } from './helpers'; self.addEventListener( 'message', message => { message = message.data; if (message.command === 'Materials') { console.log("received materials") return; } if (message.command === 'Blob' && (message.type === 'Binary' || message.type === 'Base64')) { delete message.type; unpack(message); if (Array.isArray(message.data)) message.data = message.data[0]; } let { data, task, options } = message; for (let container of data.containers) { let { id, owner, properties, meshes = [], lines = [], arcs = [], edges = [] } = container; let material = properties.material; let transfer = [], group, points, x, y, z, color, opacity; if (lines.length > 0 || arcs.length > 0 || edges.length > 0) { let line, count = 0, segments = 64; let result = container.line = { groups: [] }; let mergedLines = lines.reduce((prev, next) => prev + next.points.length, 0); let mergedEdges = edges.reduce((prev, next) => prev + (next.points.length / 3 - 1) * 6, 0); let mergedArcs = arcs.reduce((prev, next) => prev + segments * 6, 0); result.vertices = new Float32Array(mergedLines + mergedEdges + mergedArcs); transfer.push(result.vertices.buffer); result.distances = new Float32Array((mergedLines + mergedEdges + mergedArcs) / 3); transfer.push(result.distances.buffer); let firstVec, lastVec; mergedLines = 0; for (let index = 0, length = lines.length; index < length; index++) { line = lines[index]; points = line.points; if (options.materials.multi) { line.properties = { material: {}, ...line.properties }; color = line.properties.material.color || material.color || [0, 0, 0]; color = [color[0] / 255, color[1] / 255, color[2] / 255]; opacity = line.properties.material.opacity ? line.properties.material.opacity : material.opacity; opacity = typeof opacity !== 'undefined' ? opacity : 0; group = { start: mergedLines, count: points.length, index: result.groups.length, meta: { id: line.id, container: id, owner: owner, layer: line.properties.layer || properties.layer, ...line.meta, type: 'line', start: [points[0], points[1], points[2]], end: [points[points.length - 3], points[points.length - 2], points[points.length - 1]], min: [+Infinity, +Infinity, +Infinity], max: [-Infinity, -Infinity, -Infinity], material: { color, opacity } } }; if (typeof material.type !== 'undefined') group.meta.material.type = material.type; if (typeof material.linetype !== 'undefined') group.meta.material.linetype = material.linetype; result.groups.push(group); } for (let i = 0, l = points.length / 6; i < l; i++) { mergedLines += 6; firstVec = [points[i * 6 + 0], points[i * 6 + 1], points[i * 6 + 2]]; result.vertices[count++] = firstVec[0]; result.vertices[count++] = firstVec[1]; result.vertices[count++] = firstVec[2]; options.materials.multi && expand(group.meta.min, group.meta.max, firstVec); lastVec = [points[i * 6 + 3], points[i * 6 + 4], points[i * 6 + 5]]; result.vertices[count++] = lastVec[0]; result.vertices[count++] = lastVec[1]; result.vertices[count++] = lastVec[2]; options.materials.multi && expand(group.meta.min, group.meta.max, lastVec); } } for (let index = 0, length = edges.length; index < length; index++) { line = edges[index]; points = line.points; if (options.materials.multi) { line.properties = { material: {}, ...line.properties }; color = line.properties.material.color || material.color || [0, 0, 0]; color = [color[0] / 255, color[1] / 255, color[2] / 255]; opacity = line.properties.material.opacity ? line.properties.material.opacity : material.opacity; opacity = typeof opacity !== 'undefined' ? opacity : 0; group = { start: mergedLines, count: (points.length / 3 - 1) * 6, index: result.groups.length, meta: { id: line.id, container: id, owner: owner, layer: line.properties.layer || properties.layer, ...line.meta, type: 'line', start: [points[0], points[1], points[2]], end: [points[points.length - 3], points[points.length - 2], points[points.length - 1]], min: [+Infinity, +Infinity, +Infinity], max: [-Infinity, -Infinity, -Infinity], material: { color, opacity } } }; if (typeof material.type !== 'undefined') group.meta.material.type = material.type; if (typeof material.linetype !== 'undefined') group.meta.material.linetype = material.linetype; result.groups.push(group); } // Edges are line-strips, a list of points consisting of 3 floats each, [x, y, z] // In order to convert them to regular lines each endpoint will act as the next start-point for (let i = 1, l = points.length / 3; i < l; i++) { mergedLines += 6; firstVec = [points[i * 3 - 3], points[i * 3 - 2], points[i * 3 - 1]]; result.vertices[count++] = firstVec[0]; result.vertices[count++] = firstVec[1]; result.vertices[count++] = firstVec[2]; options.materials.multi && expand(group.meta.min, group.meta.max, firstVec); lastVec = [points[i * 3 + 0], points[i * 3 + 1], points[i * 3 + 2]]; result.vertices[count++] = lastVec[0]; result.vertices[count++] = lastVec[1]; result.vertices[count++] = lastVec[2]; options.materials.multi && expand(group.meta.min, group.meta.max, lastVec); } } let radius, thetaStart, thetaLength, center, zAxis, xAxis, yAxis, scalar, invScalar, segment, start; for (let index = 0, length = arcs.length; index < length; index++) { line = arcs[index]; radius = line.radius; thetaStart = 0; thetaLength = Math.abs(Math.abs(line.angle) - Math.PI) < 0.000001 ? Math.PI * 2 : line.angle; center = line.center; zAxis = line.zAxis; xAxis = line.xAxis; yAxis = line.zAxis; [x, y, z] = yAxis; yAxis[0] = y * xAxis[2] - z * xAxis[1]; yAxis[1] = z * xAxis[0] - x * xAxis[2]; yAxis[2] = x * xAxis[1] - y * xAxis[0]; scalar = Math.sqrt(yAxis[0] * yAxis[0] + yAxis[1] * yAxis[1] + yAxis[2] * yAxis[2]); if (scalar !== 0) { invScalar = 1 / scalar; yAxis[0] *= invScalar; yAxis[1] *= invScalar; yAxis[2] *= invScalar; } else { yAxis[0] = yAxis[1] = yAxis[2] = 0; } let matrix = [ xAxis[0], xAxis[1], xAxis[2], 0, yAxis[0], yAxis[1], yAxis[2], 0, zAxis[0], zAxis[1], zAxis[2], 0, center[0], center[1], center[2], 1 ]; segment = thetaStart / segments * thetaLength; lastVec = [radius * Math.cos(segment), radius * Math.sin(segment), 0]; applyMatrix(lastVec, matrix); if (options.materials.multi) { line.properties = { material: {}, ...line.properties }; color = line.properties.material.color || material.color || [0, 0, 0]; color = [color[0] / 255, color[1] / 255, color[2] / 255]; opacity = line.properties.material.opacity ? line.properties.material.opacity : material.opacity; opacity = typeof opacity !== 'undefined' ? opacity : 0; group = { start: mergedLines, count: segments * 6, index: result.groups.length, meta: { ...line.meta, id: line.id, container: id, owner: owner, layer: line.properties.layer || properties.layer, type: 'arc', circle: line.isCircle, angle: line.angle, start: lastVec, radius, thetaStart, thetaLength, center, zAxis, xAxis, yAxis, min: [+Infinity, +Infinity, +Infinity], max: [-Infinity, -Infinity, -Infinity], material: { color, opacity } } }; if (typeof material.type !== 'undefined') group.meta.material.type = material.type; if (typeof material.linetype !== 'undefined') group.meta.material.linetype = material.linetype; result.groups.push(group); expand(group.meta.min, group.meta.max, lastVec); } for (let i = 1; i <= segments; i++) { mergedLines += 6; firstVec = [lastVec[0], lastVec[1], lastVec[2]]; result.vertices[count++] = firstVec[0]; result.vertices[count++] = firstVec[1]; result.vertices[count++] = firstVec[2]; options.materials.multi && expand(group.meta.min, group.meta.max, firstVec); segment = thetaStart + i / segments * thetaLength; lastVec = [radius * Math.cos(segment), radius * Math.sin(segment), 0]; applyMatrix(lastVec, matrix); result.vertices[count++] = lastVec[0]; result.vertices[count++] = lastVec[1]; result.vertices[count++] = lastVec[2]; options.materials.multi && expand(group.meta.min, group.meta.max, lastVec); } } let d = 0, c = 0; let vertices = result.vertices; for (var i = 0, il = vertices.length / 3; i < il; i++) { if (i > 0) { d += distance( [result.vertices[i * 3 + 0], result.vertices[i * 3 + 1], result.vertices[i * 3 + 2]], [ result.vertices[(i - 1) * 3 + 0], result.vertices[(i - 1) * 3 + 1], result.vertices[(i - 1) * 3 + 2] ] ); } result.distances[c++] = d; } delete container.lines; } if (meshes.length > 0) { let mesh, mergedVertices = 0, mergedIndices = 0, mergedUvs = 0, mergedNormals = 0; let result = container.mesh = { groups: [] }; for (let index = 0, l = meshes.length; index < l; index++) { mesh = meshes[index]; mergedVertices += mesh.vertices.length; mergedIndices += mesh.indices.length; if (!!mesh.uvs) mergedUvs += mesh.uvs.length; if (!!mesh.normals) mergedNormals += mesh.normals.length; } // Merge meshes that aren't individual if (mergedVertices > 0) { result.vertices = new Float32Array(mergedVertices); transfer.push(result.vertices.buffer); result.indices = new Uint32Array(mergedIndices); transfer.push(result.indices.buffer); if (mergedUvs > 0) { result.uvs = new Float32Array(mergedUvs); transfer.push(result.uvs.buffer); } if (mergedNormals > 0) { result.normals = new Float32Array(mergedNormals); transfer.push(result.normals.buffer); } mergedVertices = 0; mergedIndices = 0; mergedUvs = 0; mergedNormals = 0; let offset = 0, indexCount = 0; for (let i = 0; i < meshes.length; i++) { mesh = meshes[i]; if (options.materials.multi) { mesh.properties = { material: {}, surface: {}, ...mesh.properties }; color = mesh.properties.material.color || material.color || [0, 0, 0]; color = [color[0] / 255, color[1] / 255, color[2] / 255]; opacity = mesh.properties.material.opacity ? mesh.properties.material.opacity : material.opacity; opacity = typeof opacity !== 'undefined' ? opacity : 0; group = { start: indexCount, count: mesh.indices.length, index: result.groups.length, meta: { ...mesh.meta, id: mesh.id, container: id, owner: owner, layer: mesh.properties.layer || properties.layer, type: mesh.properties.surface.type, ...mesh.properties.surface, min: [+Infinity, +Infinity, +Infinity], max: [-Infinity, -Infinity, -Infinity], material: { color, opacity } } }; result.groups.push(group); indexCount += mesh.indices.length; } for (let vindex = 0, vlen = mesh.vertices.length / 3; vindex < vlen; vindex++) { x = mesh.vertices[vindex * 3 + 0]; y = mesh.vertices[vindex * 3 + 1]; z = mesh.vertices[vindex * 3 + 2]; options.materials.multi && expand(group.meta.min, group.meta.max, [x, y, z]); result.vertices[mergedVertices++] = x; result.vertices[mergedVertices++] = y; result.vertices[mergedVertices++] = z; } for (let findex = 0, flen = mesh.indices.length; findex < flen; findex++) { result.indices[mergedIndices++] = mesh.indices[findex] + offset; } if (!!mesh.uvs) { for (let uvindex = 0, uvlen = mesh.uvs.length; uvindex < uvlen; uvindex++) { result.uvs[mergedUvs++] = mesh.uvs[uvindex]; } } if (!!mesh.normals) { for (let nindex = 0, nlen = mesh.normals.length; nindex < nlen; nindex++) { result.normals[mergedNormals++] = mesh.normals[nindex]; } } offset += mesh.vertices.length / 3; } } delete container.meshes; } self.postMessage( { action: 'Result', result: container, task: task }, transfer ); } self.postMessage({ action: 'Finished', task: task }); }, false );