awv3
Version:
⚡ AWV3 embedded CAD
417 lines (370 loc) • 19.7 kB
JavaScript
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
);