awv3
Version:
⚡ AWV3 embedded CAD
202 lines (174 loc) • 7.77 kB
JavaScript
import * as THREE from 'three';
import Defaults from './defaults';
export function parseLine(data, context) {
let { options } = context;
let { id, line: { groups } } = data;
// Create mesh
let geom = new THREE.LineSegments();
geom.renderOrder = options.renderOrder.LineSegments;
geom.userData = { id: 0, parentId: id, refs: groups.map(group => group.meta) };
// Create geometry
geom.geometry = new THREE.BufferGeometry();
geom.geometry.addAttribute('position', new THREE.BufferAttribute(data.line.vertices, 3));
geom.geometry.groups = [];
// lineDistances have to apply to the entire object if a single dashed material is among it, it can't be
// set in a groups scope individually
data.line.distances &&
geom.geometry.addAttribute('lineDistance', new THREE.BufferAttribute(data.line.distances, 1));
if (options.materials.multi) {
geom.material = groups.map(group => {
convertVectors(group.meta);
geom.geometry.groups.push({
start: group.start / 3,
count: group.count / 3,
materialIndex: group.index,
meta: group.meta,
});
let lineShader = options.lineShader;
let lineOptions = options.lineShaderOptions;
if (group.meta.material.linetype === 'DASHED') {
lineShader = THREE.LineDashedMaterial;
lineOptions = {
...lineOptions,
dashSize: 2,
gapSize: 2,
};
}
group.meta.material.color = lineOptions.color || new THREE.Color(...group.meta.material.color);
group.meta.material.opacity = typeof lineOptions.opacity !== 'undefined'
? lineOptions.opacity
: group.meta.material.opacity;
let material = new lineShader({
...lineOptions,
color: group.meta.material.color,
opacity: group.meta.material.opacity,
});
material.meta = group.meta;
material.parent = geom;
return material;
});
} else {
data.properties.material.color = options.lineShaderOptions.color || data.properties.material.color;
data.properties.material.opacity = typeof options.lineShaderOptions.opacity !== 'undefined'
? options.lineShaderOptions.opacity
: data.properties.material.opacity;
geom.material = new options.lineShader({
...options.lineShaderOptions,
color: data.properties.material.color,
opacity: data.properties.material.opacity,
});
geom.material.parent = geom;
}
return finalize(geom, data, groups);
}
export function parseMesh(data, context) {
let { options } = context;
let { id, mesh: { groups } } = data;
// Create mesh
let geom = new THREE.Mesh();
if (options.materials.shadows) {
geom.castShadow = true;
geom.receiveShadow = true;
}
geom.renderOrder = options.renderOrder.Mesh;
geom.userData = { id: 0, parentId: id, refs: groups.map(group => group.meta) };
// Create geometry
if (options.materials.multi) {
geom.geometry = new THREE.Geometry();
for (let index = 0, length = data.mesh.vertices.length / 3; index < length; index++)
geom.geometry.vertices.push(
new THREE.Vector3(
data.mesh.vertices[index * 3 + 0],
data.mesh.vertices[index * 3 + 1],
data.mesh.vertices[index * 3 + 2],
),
);
let i1, i2, i3, normal, groupCount = 0;
let group = groups[groupCount++];
for (let index = 0, length = data.mesh.indices.length / 3; index < length; index++) {
if (group.start + group.count <= index * 3) group = groups[groupCount++];
i1 = data.mesh.indices[index * 3 + 0];
i2 = data.mesh.indices[index * 3 + 1];
i3 = data.mesh.indices[index * 3 + 2];
normal = data.mesh.normals
? [
new THREE.Vector3(
data.mesh.normals[i1 * 3 + 0],
data.mesh.normals[i1 * 3 + 1],
data.mesh.normals[i1 * 3 + 2],
),
new THREE.Vector3(
data.mesh.normals[i2 * 3 + 0],
data.mesh.normals[i2 * 3 + 1],
data.mesh.normals[i2 * 3 + 2],
),
new THREE.Vector3(
data.mesh.normals[i3 * 3 + 0],
data.mesh.normals[i3 * 3 + 1],
data.mesh.normals[i3 * 3 + 2],
),
]
: undefined;
geom.geometry.faces.push(new THREE.Face3(i1, i2, i3, normal, undefined, group.index));
}
if (!data.mesh.normals) geom.geometry.computeVertexNormals();
} else {
geom.geometry = new THREE.BufferGeometry();
geom.geometry.addAttribute('position', new THREE.BufferAttribute(data.mesh.vertices, 3));
geom.geometry.setIndex(new THREE.BufferAttribute(data.mesh.indices, 1));
if (!!data.mesh.normals) geom.geometry.addAttribute('normal', new THREE.BufferAttribute(data.mesh.normals, 3));
else geom.geometry.computeVertexNormals();
!!data.mesh.uvs && geom.geometry.addAttribute('uv', new THREE.BufferAttribute(data.mesh.uvs, 2));
}
// Create materials
if (options.materials.multi) {
geom.material = groups.map(group => {
convertVectors(group.meta);
group.meta.material.color =
options.meshShaderOptions.color || new THREE.Color(...group.meta.material.color);
group.meta.material.opacity = typeof options.meshShaderOptions.opacity !== 'undefined'
? options.meshShaderOptions.opacity
: group.meta.material.opacity;
let material = new options.meshShader({
...options.meshShaderOptions,
color: group.meta.material.color,
opacity: group.meta.material.opacity,
});
material.meta = group.meta;
material.parent = geom;
return material;
});
} else {
data.properties.material.color = options.meshShaderOptions.color || data.properties.material.color;
data.properties.material.opacity = typeof options.meshShaderOptions.opacity !== 'undefined'
? options.meshShaderOptions.opacity
: data.properties.material.opacity;
geom.material = new options.meshShader({
...options.meshShaderOptions,
...data.properties.material,
color: data.properties.material.color,
opacity: data.properties.material.opacity,
});
geom.material.parent = geom;
}
return finalize(geom, data, groups);
}
function convertVectors(meta) {
meta.box = new THREE.Box3(new THREE.Vector3(...meta.min), new THREE.Vector3(...meta.max));
delete meta.min;
delete meta.max;
for (let key in meta) {
let item = meta[key];
if (Array.isArray(item) && item.length == 3) meta[key] = new THREE.Vector3().fromArray(item);
}
}
function finalize(geom, data, groups) {
if (!!data.properties.box) {
geom.geometry.boundingBox = data.properties.box;
geom.geometry.boundingSphere = data.properties.sphere;
} else {
geom.geometry.computeBoundingBox();
geom.geometry.computeBoundingSphere();
}
return geom;
}