UNPKG

three-stdlib

Version:

stand-alone library of threejs examples

854 lines (853 loc) 34.8 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const THREE = require("three"); const fflate = require("fflate"); const LoaderUtils = require("../_polyfill/LoaderUtils.cjs"); class ThreeMFLoader extends THREE.Loader { constructor(manager) { super(manager); this.availableExtensions = []; } load(url, onLoad, onProgress, onError) { const scope = this; const loader = new THREE.FileLoader(scope.manager); loader.setPath(scope.path); loader.setResponseType("arraybuffer"); loader.setRequestHeader(scope.requestHeader); loader.setWithCredentials(scope.withCredentials); loader.load( url, function(buffer) { try { onLoad(scope.parse(buffer)); } catch (e) { if (onError) { onError(e); } else { console.error(e); } scope.manager.itemError(url); } }, onProgress, onError ); } parse(data) { const scope = this; const textureLoader = new THREE.TextureLoader(this.manager); function loadDocument(data2) { let zip = null; let file = null; let relsName; let modelRelsName; const modelPartNames = []; const texturesPartNames = []; let modelRels; const modelParts = {}; const printTicketParts = {}; const texturesParts = {}; const otherParts = {}; try { zip = fflate.unzipSync(new Uint8Array(data2)); } catch (e) { if (e instanceof ReferenceError) { console.error("THREE.3MFLoader: fflate missing and file is compressed."); return null; } } for (file in zip) { if (file.match(/\_rels\/.rels$/)) { relsName = file; } else if (file.match(/3D\/_rels\/.*\.model\.rels$/)) { modelRelsName = file; } else if (file.match(/^3D\/.*\.model$/)) { modelPartNames.push(file); } else if (file.match(/^3D\/Metadata\/.*\.xml$/)) ; else if (file.match(/^3D\/Textures?\/.*/)) { texturesPartNames.push(file); } else if (file.match(/^3D\/Other\/.*/)) ; } const relsView = zip[relsName]; const relsFileText = LoaderUtils.decodeText(relsView); const rels = parseRelsXml(relsFileText); if (modelRelsName) { const relsView2 = zip[modelRelsName]; const relsFileText2 = LoaderUtils.decodeText(relsView2); modelRels = parseRelsXml(relsFileText2); } for (let i = 0; i < modelPartNames.length; i++) { const modelPart = modelPartNames[i]; const view = zip[modelPart]; const fileText = LoaderUtils.decodeText(view); const xmlData = new DOMParser().parseFromString(fileText, "application/xml"); if (xmlData.documentElement.nodeName.toLowerCase() !== "model") { console.error("THREE.3MFLoader: Error loading 3MF - no 3MF document found: ", modelPart); } const modelNode = xmlData.querySelector("model"); const extensions = {}; for (let i2 = 0; i2 < modelNode.attributes.length; i2++) { const attr = modelNode.attributes[i2]; if (attr.name.match(/^xmlns:(.+)$/)) { extensions[attr.value] = RegExp.$1; } } const modelData = parseModelNode(modelNode); modelData["xml"] = modelNode; if (0 < Object.keys(extensions).length) { modelData["extensions"] = extensions; } modelParts[modelPart] = modelData; } for (let i = 0; i < texturesPartNames.length; i++) { const texturesPartName = texturesPartNames[i]; texturesParts[texturesPartName] = zip[texturesPartName].buffer; } return { rels, modelRels, model: modelParts, printTicket: printTicketParts, texture: texturesParts, other: otherParts }; } function parseRelsXml(relsFileText) { const relationships = []; const relsXmlData = new DOMParser().parseFromString(relsFileText, "application/xml"); const relsNodes = relsXmlData.querySelectorAll("Relationship"); for (let i = 0; i < relsNodes.length; i++) { const relsNode = relsNodes[i]; const relationship = { target: relsNode.getAttribute("Target"), //required id: relsNode.getAttribute("Id"), //required type: relsNode.getAttribute("Type") //required }; relationships.push(relationship); } return relationships; } function parseMetadataNodes(metadataNodes) { const metadataData = {}; for (let i = 0; i < metadataNodes.length; i++) { const metadataNode = metadataNodes[i]; const name = metadataNode.getAttribute("name"); const validNames = [ "Title", "Designer", "Description", "Copyright", "LicenseTerms", "Rating", "CreationDate", "ModificationDate" ]; if (0 <= validNames.indexOf(name)) { metadataData[name] = metadataNode.textContent; } } return metadataData; } function parseBasematerialsNode(basematerialsNode) { const basematerialsData = { id: basematerialsNode.getAttribute("id"), // required basematerials: [] }; const basematerialNodes = basematerialsNode.querySelectorAll("base"); for (let i = 0; i < basematerialNodes.length; i++) { const basematerialNode = basematerialNodes[i]; const basematerialData = parseBasematerialNode(basematerialNode); basematerialData.index = i; basematerialsData.basematerials.push(basematerialData); } return basematerialsData; } function parseTexture2DNode(texture2DNode) { const texture2dData = { id: texture2DNode.getAttribute("id"), // required path: texture2DNode.getAttribute("path"), // required contenttype: texture2DNode.getAttribute("contenttype"), // required tilestyleu: texture2DNode.getAttribute("tilestyleu"), tilestylev: texture2DNode.getAttribute("tilestylev"), filter: texture2DNode.getAttribute("filter") }; return texture2dData; } function parseTextures2DGroupNode(texture2DGroupNode) { const texture2DGroupData = { id: texture2DGroupNode.getAttribute("id"), // required texid: texture2DGroupNode.getAttribute("texid"), // required displaypropertiesid: texture2DGroupNode.getAttribute("displaypropertiesid") }; const tex2coordNodes = texture2DGroupNode.querySelectorAll("tex2coord"); const uvs = []; for (let i = 0; i < tex2coordNodes.length; i++) { const tex2coordNode = tex2coordNodes[i]; const u = tex2coordNode.getAttribute("u"); const v = tex2coordNode.getAttribute("v"); uvs.push(parseFloat(u), parseFloat(v)); } texture2DGroupData["uvs"] = new Float32Array(uvs); return texture2DGroupData; } function parseColorGroupNode(colorGroupNode) { const colorGroupData = { id: colorGroupNode.getAttribute("id"), // required displaypropertiesid: colorGroupNode.getAttribute("displaypropertiesid") }; const colorNodes = colorGroupNode.querySelectorAll("color"); const colors = []; const colorObject = new THREE.Color(); for (let i = 0; i < colorNodes.length; i++) { const colorNode = colorNodes[i]; const color = colorNode.getAttribute("color"); colorObject.setStyle(color.substring(0, 7)); colorObject.convertSRGBToLinear(); colors.push(colorObject.r, colorObject.g, colorObject.b); } colorGroupData["colors"] = new Float32Array(colors); return colorGroupData; } function parseMetallicDisplaypropertiesNode(metallicDisplaypropetiesNode) { const metallicDisplaypropertiesData = { id: metallicDisplaypropetiesNode.getAttribute("id") // required }; const metallicNodes = metallicDisplaypropetiesNode.querySelectorAll("pbmetallic"); const metallicData = []; for (let i = 0; i < metallicNodes.length; i++) { const metallicNode = metallicNodes[i]; metallicData.push({ name: metallicNode.getAttribute("name"), // required metallicness: parseFloat(metallicNode.getAttribute("metallicness")), // required roughness: parseFloat(metallicNode.getAttribute("roughness")) // required }); } metallicDisplaypropertiesData.data = metallicData; return metallicDisplaypropertiesData; } function parseBasematerialNode(basematerialNode) { const basematerialData = {}; basematerialData["name"] = basematerialNode.getAttribute("name"); basematerialData["displaycolor"] = basematerialNode.getAttribute("displaycolor"); basematerialData["displaypropertiesid"] = basematerialNode.getAttribute("displaypropertiesid"); return basematerialData; } function parseMeshNode(meshNode) { const meshData = {}; const vertices = []; const vertexNodes = meshNode.querySelectorAll("vertices vertex"); for (let i = 0; i < vertexNodes.length; i++) { const vertexNode = vertexNodes[i]; const x = vertexNode.getAttribute("x"); const y = vertexNode.getAttribute("y"); const z = vertexNode.getAttribute("z"); vertices.push(parseFloat(x), parseFloat(y), parseFloat(z)); } meshData["vertices"] = new Float32Array(vertices); const triangleProperties = []; const triangles = []; const triangleNodes = meshNode.querySelectorAll("triangles triangle"); for (let i = 0; i < triangleNodes.length; i++) { const triangleNode = triangleNodes[i]; const v1 = triangleNode.getAttribute("v1"); const v2 = triangleNode.getAttribute("v2"); const v3 = triangleNode.getAttribute("v3"); const p1 = triangleNode.getAttribute("p1"); const p2 = triangleNode.getAttribute("p2"); const p3 = triangleNode.getAttribute("p3"); const pid = triangleNode.getAttribute("pid"); const triangleProperty = {}; triangleProperty["v1"] = parseInt(v1, 10); triangleProperty["v2"] = parseInt(v2, 10); triangleProperty["v3"] = parseInt(v3, 10); triangles.push(triangleProperty["v1"], triangleProperty["v2"], triangleProperty["v3"]); if (p1) { triangleProperty["p1"] = parseInt(p1, 10); } if (p2) { triangleProperty["p2"] = parseInt(p2, 10); } if (p3) { triangleProperty["p3"] = parseInt(p3, 10); } if (pid) { triangleProperty["pid"] = pid; } if (0 < Object.keys(triangleProperty).length) { triangleProperties.push(triangleProperty); } } meshData["triangleProperties"] = triangleProperties; meshData["triangles"] = new Uint32Array(triangles); return meshData; } function parseComponentsNode(componentsNode) { const components = []; const componentNodes = componentsNode.querySelectorAll("component"); for (let i = 0; i < componentNodes.length; i++) { const componentNode = componentNodes[i]; const componentData = parseComponentNode(componentNode); components.push(componentData); } return components; } function parseComponentNode(componentNode) { const componentData = {}; componentData["objectId"] = componentNode.getAttribute("objectid"); const transform = componentNode.getAttribute("transform"); if (transform) { componentData["transform"] = parseTransform(transform); } return componentData; } function parseTransform(transform) { const t = []; transform.split(" ").forEach(function(s) { t.push(parseFloat(s)); }); const matrix = new THREE.Matrix4(); matrix.set(t[0], t[3], t[6], t[9], t[1], t[4], t[7], t[10], t[2], t[5], t[8], t[11], 0, 0, 0, 1); return matrix; } function parseObjectNode(objectNode) { const objectData = { type: objectNode.getAttribute("type") }; const id = objectNode.getAttribute("id"); if (id) { objectData["id"] = id; } const pid = objectNode.getAttribute("pid"); if (pid) { objectData["pid"] = pid; } const pindex = objectNode.getAttribute("pindex"); if (pindex) { objectData["pindex"] = pindex; } const thumbnail = objectNode.getAttribute("thumbnail"); if (thumbnail) { objectData["thumbnail"] = thumbnail; } const partnumber = objectNode.getAttribute("partnumber"); if (partnumber) { objectData["partnumber"] = partnumber; } const name = objectNode.getAttribute("name"); if (name) { objectData["name"] = name; } const meshNode = objectNode.querySelector("mesh"); if (meshNode) { objectData["mesh"] = parseMeshNode(meshNode); } const componentsNode = objectNode.querySelector("components"); if (componentsNode) { objectData["components"] = parseComponentsNode(componentsNode); } return objectData; } function parseResourcesNode(resourcesNode) { const resourcesData = {}; resourcesData["basematerials"] = {}; const basematerialsNodes = resourcesNode.querySelectorAll("basematerials"); for (let i = 0; i < basematerialsNodes.length; i++) { const basematerialsNode = basematerialsNodes[i]; const basematerialsData = parseBasematerialsNode(basematerialsNode); resourcesData["basematerials"][basematerialsData["id"]] = basematerialsData; } resourcesData["texture2d"] = {}; const textures2DNodes = resourcesNode.querySelectorAll("texture2d"); for (let i = 0; i < textures2DNodes.length; i++) { const textures2DNode = textures2DNodes[i]; const texture2DData = parseTexture2DNode(textures2DNode); resourcesData["texture2d"][texture2DData["id"]] = texture2DData; } resourcesData["colorgroup"] = {}; const colorGroupNodes = resourcesNode.querySelectorAll("colorgroup"); for (let i = 0; i < colorGroupNodes.length; i++) { const colorGroupNode = colorGroupNodes[i]; const colorGroupData = parseColorGroupNode(colorGroupNode); resourcesData["colorgroup"][colorGroupData["id"]] = colorGroupData; } resourcesData["pbmetallicdisplayproperties"] = {}; const pbmetallicdisplaypropertiesNodes = resourcesNode.querySelectorAll("pbmetallicdisplayproperties"); for (let i = 0; i < pbmetallicdisplaypropertiesNodes.length; i++) { const pbmetallicdisplaypropertiesNode = pbmetallicdisplaypropertiesNodes[i]; const pbmetallicdisplaypropertiesData = parseMetallicDisplaypropertiesNode(pbmetallicdisplaypropertiesNode); resourcesData["pbmetallicdisplayproperties"][pbmetallicdisplaypropertiesData["id"]] = pbmetallicdisplaypropertiesData; } resourcesData["texture2dgroup"] = {}; const textures2DGroupNodes = resourcesNode.querySelectorAll("texture2dgroup"); for (let i = 0; i < textures2DGroupNodes.length; i++) { const textures2DGroupNode = textures2DGroupNodes[i]; const textures2DGroupData = parseTextures2DGroupNode(textures2DGroupNode); resourcesData["texture2dgroup"][textures2DGroupData["id"]] = textures2DGroupData; } resourcesData["object"] = {}; const objectNodes = resourcesNode.querySelectorAll("object"); for (let i = 0; i < objectNodes.length; i++) { const objectNode = objectNodes[i]; const objectData = parseObjectNode(objectNode); resourcesData["object"][objectData["id"]] = objectData; } return resourcesData; } function parseBuildNode(buildNode) { const buildData = []; const itemNodes = buildNode.querySelectorAll("item"); for (let i = 0; i < itemNodes.length; i++) { const itemNode = itemNodes[i]; const buildItem = { objectId: itemNode.getAttribute("objectid") }; const transform = itemNode.getAttribute("transform"); if (transform) { buildItem["transform"] = parseTransform(transform); } buildData.push(buildItem); } return buildData; } function parseModelNode(modelNode) { const modelData = { unit: modelNode.getAttribute("unit") || "millimeter" }; const metadataNodes = modelNode.querySelectorAll("metadata"); if (metadataNodes) { modelData["metadata"] = parseMetadataNodes(metadataNodes); } const resourcesNode = modelNode.querySelector("resources"); if (resourcesNode) { modelData["resources"] = parseResourcesNode(resourcesNode); } const buildNode = modelNode.querySelector("build"); if (buildNode) { modelData["build"] = parseBuildNode(buildNode); } return modelData; } function buildTexture(texture2dgroup, objects2, modelData, textureData) { const texid = texture2dgroup.texid; const texture2ds = modelData.resources.texture2d; const texture2d = texture2ds[texid]; if (texture2d) { const data2 = textureData[texture2d.path]; const type = texture2d.contenttype; const blob = new Blob([data2], { type }); const sourceURI = URL.createObjectURL(blob); const texture = textureLoader.load(sourceURI, function() { URL.revokeObjectURL(sourceURI); }); if ("colorSpace" in texture) texture.colorSpace = "srgb"; else texture.encoding = 3001; switch (texture2d.tilestyleu) { case "wrap": texture.wrapS = THREE.RepeatWrapping; break; case "mirror": texture.wrapS = THREE.MirroredRepeatWrapping; break; case "none": case "clamp": texture.wrapS = THREE.ClampToEdgeWrapping; break; default: texture.wrapS = THREE.RepeatWrapping; } switch (texture2d.tilestylev) { case "wrap": texture.wrapT = THREE.RepeatWrapping; break; case "mirror": texture.wrapT = THREE.MirroredRepeatWrapping; break; case "none": case "clamp": texture.wrapT = THREE.ClampToEdgeWrapping; break; default: texture.wrapT = THREE.RepeatWrapping; } switch (texture2d.filter) { case "auto": texture.magFilter = THREE.LinearFilter; texture.minFilter = THREE.LinearMipmapLinearFilter; break; case "linear": texture.magFilter = THREE.LinearFilter; texture.minFilter = THREE.LinearFilter; break; case "nearest": texture.magFilter = THREE.NearestFilter; texture.minFilter = THREE.NearestFilter; break; default: texture.magFilter = THREE.LinearFilter; texture.minFilter = THREE.LinearMipmapLinearFilter; } return texture; } else { return null; } } function buildBasematerialsMeshes(basematerials, triangleProperties, meshData, objects2, modelData, textureData, objectData) { const objectPindex = objectData.pindex; const materialMap = {}; for (let i = 0, l = triangleProperties.length; i < l; i++) { const triangleProperty = triangleProperties[i]; const pindex = triangleProperty.p1 !== void 0 ? triangleProperty.p1 : objectPindex; if (materialMap[pindex] === void 0) materialMap[pindex] = []; materialMap[pindex].push(triangleProperty); } const keys = Object.keys(materialMap); const meshes = []; for (let i = 0, l = keys.length; i < l; i++) { const materialIndex = keys[i]; const trianglePropertiesProps = materialMap[materialIndex]; const basematerialData = basematerials.basematerials[materialIndex]; const material = getBuild(basematerialData, objects2, modelData, textureData, objectData, buildBasematerial); const geometry = new THREE.BufferGeometry(); const positionData = []; const vertices = meshData.vertices; for (let j = 0, jl = trianglePropertiesProps.length; j < jl; j++) { const triangleProperty = trianglePropertiesProps[j]; positionData.push(vertices[triangleProperty.v1 * 3 + 0]); positionData.push(vertices[triangleProperty.v1 * 3 + 1]); positionData.push(vertices[triangleProperty.v1 * 3 + 2]); positionData.push(vertices[triangleProperty.v2 * 3 + 0]); positionData.push(vertices[triangleProperty.v2 * 3 + 1]); positionData.push(vertices[triangleProperty.v2 * 3 + 2]); positionData.push(vertices[triangleProperty.v3 * 3 + 0]); positionData.push(vertices[triangleProperty.v3 * 3 + 1]); positionData.push(vertices[triangleProperty.v3 * 3 + 2]); } geometry.setAttribute("position", new THREE.Float32BufferAttribute(positionData, 3)); const mesh = new THREE.Mesh(geometry, material); meshes.push(mesh); } return meshes; } function buildTexturedMesh(texture2dgroup, triangleProperties, meshData, objects2, modelData, textureData, objectData) { const geometry = new THREE.BufferGeometry(); const positionData = []; const uvData = []; const vertices = meshData.vertices; const uvs = texture2dgroup.uvs; for (let i = 0, l = triangleProperties.length; i < l; i++) { const triangleProperty = triangleProperties[i]; positionData.push(vertices[triangleProperty.v1 * 3 + 0]); positionData.push(vertices[triangleProperty.v1 * 3 + 1]); positionData.push(vertices[triangleProperty.v1 * 3 + 2]); positionData.push(vertices[triangleProperty.v2 * 3 + 0]); positionData.push(vertices[triangleProperty.v2 * 3 + 1]); positionData.push(vertices[triangleProperty.v2 * 3 + 2]); positionData.push(vertices[triangleProperty.v3 * 3 + 0]); positionData.push(vertices[triangleProperty.v3 * 3 + 1]); positionData.push(vertices[triangleProperty.v3 * 3 + 2]); uvData.push(uvs[triangleProperty.p1 * 2 + 0]); uvData.push(uvs[triangleProperty.p1 * 2 + 1]); uvData.push(uvs[triangleProperty.p2 * 2 + 0]); uvData.push(uvs[triangleProperty.p2 * 2 + 1]); uvData.push(uvs[triangleProperty.p3 * 2 + 0]); uvData.push(uvs[triangleProperty.p3 * 2 + 1]); } geometry.setAttribute("position", new THREE.Float32BufferAttribute(positionData, 3)); geometry.setAttribute("uv", new THREE.Float32BufferAttribute(uvData, 2)); const texture = getBuild(texture2dgroup, objects2, modelData, textureData, objectData, buildTexture); const material = new THREE.MeshPhongMaterial({ map: texture, flatShading: true }); const mesh = new THREE.Mesh(geometry, material); return mesh; } function buildVertexColorMesh(colorgroup, triangleProperties, meshData, objects2, modelData, objectData) { const geometry = new THREE.BufferGeometry(); const positionData = []; const colorData = []; const vertices = meshData.vertices; const colors = colorgroup.colors; for (let i = 0, l = triangleProperties.length; i < l; i++) { const triangleProperty = triangleProperties[i]; const v1 = triangleProperty.v1; const v2 = triangleProperty.v2; const v3 = triangleProperty.v3; positionData.push(vertices[v1 * 3 + 0]); positionData.push(vertices[v1 * 3 + 1]); positionData.push(vertices[v1 * 3 + 2]); positionData.push(vertices[v2 * 3 + 0]); positionData.push(vertices[v2 * 3 + 1]); positionData.push(vertices[v2 * 3 + 2]); positionData.push(vertices[v3 * 3 + 0]); positionData.push(vertices[v3 * 3 + 1]); positionData.push(vertices[v3 * 3 + 2]); const p1 = triangleProperty.p1 !== void 0 ? triangleProperty.p1 : objectData.pindex; const p2 = triangleProperty.p2 !== void 0 ? triangleProperty.p2 : p1; const p3 = triangleProperty.p3 !== void 0 ? triangleProperty.p3 : p1; colorData.push(colors[p1 * 3 + 0]); colorData.push(colors[p1 * 3 + 1]); colorData.push(colors[p1 * 3 + 2]); colorData.push(colors[p2 * 3 + 0]); colorData.push(colors[p2 * 3 + 1]); colorData.push(colors[p2 * 3 + 2]); colorData.push(colors[p3 * 3 + 0]); colorData.push(colors[p3 * 3 + 1]); colorData.push(colors[p3 * 3 + 2]); } geometry.setAttribute("position", new THREE.Float32BufferAttribute(positionData, 3)); geometry.setAttribute("color", new THREE.Float32BufferAttribute(colorData, 3)); const material = new THREE.MeshPhongMaterial({ vertexColors: true, flatShading: true }); const mesh = new THREE.Mesh(geometry, material); return mesh; } function buildDefaultMesh(meshData) { const geometry = new THREE.BufferGeometry(); geometry.setIndex(new THREE.BufferAttribute(meshData["triangles"], 1)); geometry.setAttribute("position", new THREE.BufferAttribute(meshData["vertices"], 3)); const material = new THREE.MeshPhongMaterial({ color: 11184895, flatShading: true }); const mesh = new THREE.Mesh(geometry, material); return mesh; } function buildMeshes(resourceMap, meshData, objects2, modelData, textureData, objectData) { const keys = Object.keys(resourceMap); const meshes = []; for (let i = 0, il = keys.length; i < il; i++) { const resourceId = keys[i]; const triangleProperties = resourceMap[resourceId]; const resourceType = getResourceType(resourceId, modelData); switch (resourceType) { case "material": const basematerials = modelData.resources.basematerials[resourceId]; const newMeshes = buildBasematerialsMeshes( basematerials, triangleProperties, meshData, objects2, modelData, textureData, objectData ); for (let j = 0, jl = newMeshes.length; j < jl; j++) { meshes.push(newMeshes[j]); } break; case "texture": const texture2dgroup = modelData.resources.texture2dgroup[resourceId]; meshes.push( buildTexturedMesh( texture2dgroup, triangleProperties, meshData, objects2, modelData, textureData, objectData ) ); break; case "vertexColors": const colorgroup = modelData.resources.colorgroup[resourceId]; meshes.push(buildVertexColorMesh(colorgroup, triangleProperties, meshData, objects2, modelData, objectData)); break; case "default": meshes.push(buildDefaultMesh(meshData)); break; default: console.error("THREE.3MFLoader: Unsupported resource type."); } } return meshes; } function getResourceType(pid, modelData) { if (modelData.resources.texture2dgroup[pid] !== void 0) { return "texture"; } else if (modelData.resources.basematerials[pid] !== void 0) { return "material"; } else if (modelData.resources.colorgroup[pid] !== void 0) { return "vertexColors"; } else if (pid === "default") { return "default"; } else { return void 0; } } function analyzeObject(modelData, meshData, objectData) { const resourceMap = {}; const triangleProperties = meshData["triangleProperties"]; const objectPid = objectData.pid; for (let i = 0, l = triangleProperties.length; i < l; i++) { const triangleProperty = triangleProperties[i]; let pid = triangleProperty.pid !== void 0 ? triangleProperty.pid : objectPid; if (pid === void 0) pid = "default"; if (resourceMap[pid] === void 0) resourceMap[pid] = []; resourceMap[pid].push(triangleProperty); } return resourceMap; } function buildGroup(meshData, objects2, modelData, textureData, objectData) { const group = new THREE.Group(); const resourceMap = analyzeObject(modelData, meshData, objectData); const meshes = buildMeshes(resourceMap, meshData, objects2, modelData, textureData, objectData); for (let i = 0, l = meshes.length; i < l; i++) { group.add(meshes[i]); } return group; } function applyExtensions(extensions, meshData, modelXml) { if (!extensions) { return; } const availableExtensions = []; const keys = Object.keys(extensions); for (let i = 0; i < keys.length; i++) { const ns = keys[i]; for (let j = 0; j < scope.availableExtensions.length; j++) { const extension = scope.availableExtensions[j]; if (extension.ns === ns) { availableExtensions.push(extension); } } } for (let i = 0; i < availableExtensions.length; i++) { const extension = availableExtensions[i]; extension.apply(modelXml, extensions[extension["ns"]], meshData); } } function getBuild(data2, objects2, modelData, textureData, objectData, builder) { if (data2.build !== void 0) return data2.build; data2.build = builder(data2, objects2, modelData, textureData, objectData); return data2.build; } function buildBasematerial(materialData, objects2, modelData) { let material; const displaypropertiesid = materialData.displaypropertiesid; const pbmetallicdisplayproperties = modelData.resources.pbmetallicdisplayproperties; if (displaypropertiesid !== null && pbmetallicdisplayproperties[displaypropertiesid] !== void 0) { const pbmetallicdisplayproperty = pbmetallicdisplayproperties[displaypropertiesid]; const metallicData = pbmetallicdisplayproperty.data[materialData.index]; material = new THREE.MeshStandardMaterial({ flatShading: true, roughness: metallicData.roughness, metalness: metallicData.metallicness }); } else { material = new THREE.MeshPhongMaterial({ flatShading: true }); } material.name = materialData.name; const displaycolor = materialData.displaycolor; const color = displaycolor.substring(0, 7); material.color.setStyle(color); material.color.convertSRGBToLinear(); if (displaycolor.length === 9) { material.opacity = parseInt(displaycolor.charAt(7) + displaycolor.charAt(8), 16) / 255; } return material; } function buildComposite(compositeData, objects2, modelData, textureData) { const composite = new THREE.Group(); for (let j = 0; j < compositeData.length; j++) { const component = compositeData[j]; let build2 = objects2[component.objectId]; if (build2 === void 0) { buildObject(component.objectId, objects2, modelData, textureData); build2 = objects2[component.objectId]; } const object3D = build2.clone(); const transform = component.transform; if (transform) { object3D.applyMatrix4(transform); } composite.add(object3D); } return composite; } function buildObject(objectId, objects2, modelData, textureData) { const objectData = modelData["resources"]["object"][objectId]; if (objectData["mesh"]) { const meshData = objectData["mesh"]; const extensions = modelData["extensions"]; const modelXml = modelData["xml"]; applyExtensions(extensions, meshData, modelXml); objects2[objectData.id] = getBuild(meshData, objects2, modelData, textureData, objectData, buildGroup); } else { const compositeData = objectData["components"]; objects2[objectData.id] = getBuild(compositeData, objects2, modelData, textureData, objectData, buildComposite); } } function buildObjects(data3mf2) { const modelsData = data3mf2.model; const modelRels = data3mf2.modelRels; const objects2 = {}; const modelsKeys = Object.keys(modelsData); const textureData = {}; if (modelRels) { for (let i = 0, l = modelRels.length; i < l; i++) { const modelRel = modelRels[i]; const textureKey = modelRel.target.substring(1); if (data3mf2.texture[textureKey]) { textureData[modelRel.target] = data3mf2.texture[textureKey]; } } } for (let i = 0; i < modelsKeys.length; i++) { const modelsKey = modelsKeys[i]; const modelData = modelsData[modelsKey]; const objectIds = Object.keys(modelData["resources"]["object"]); for (let j = 0; j < objectIds.length; j++) { const objectId = objectIds[j]; buildObject(objectId, objects2, modelData, textureData); } } return objects2; } function fetch3DModelPart(rels) { for (let i = 0; i < rels.length; i++) { const rel = rels[i]; const extension = rel.target.split(".").pop(); if (extension.toLowerCase() === "model") return rel; } } function build(objects2, data3mf2) { const group = new THREE.Group(); const relationship = fetch3DModelPart(data3mf2["rels"]); const buildData = data3mf2.model[relationship["target"].substring(1)]["build"]; for (let i = 0; i < buildData.length; i++) { const buildItem = buildData[i]; const object3D = objects2[buildItem["objectId"]]; const transform = buildItem["transform"]; if (transform) { object3D.applyMatrix4(transform); } group.add(object3D); } return group; } const data3mf = loadDocument(data); const objects = buildObjects(data3mf); return build(objects, data3mf); } addExtension(extension) { this.availableExtensions.push(extension); } } exports.ThreeMFLoader = ThreeMFLoader; //# sourceMappingURL=3MFLoader.cjs.map