{"version":3,"file":"LDrawLoader.cjs","sources":["../../src/loaders/LDrawLoader.js"],"sourcesContent":["import {\n  BufferAttribute,\n  BufferGeometry,\n  Color,\n  FileLoader,\n  Group,\n  LineBasicMaterial,\n  LineSegments,\n  Loader,\n  Matrix4,\n  Mesh,\n  MeshStandardMaterial,\n  ShaderMaterial,\n  UniformsLib,\n  UniformsUtils,\n  Vector3,\n  Ray,\n} from 'three'\nimport { version } from '../_polyfill/constants'\n\n// Special surface finish tag types.\n// Note: \"MATERIAL\" tag (e.g. GLITTER, SPECKLE) is not implemented\nconst FINISH_TYPE_DEFAULT = 0\nconst FINISH_TYPE_CHROME = 1\nconst FINISH_TYPE_PEARLESCENT = 2\nconst FINISH_TYPE_RUBBER = 3\nconst FINISH_TYPE_MATTE_METALLIC = 4\nconst FINISH_TYPE_METAL = 5\n\n// State machine to search a subobject path.\n// The LDraw standard establishes these various possible subfolders.\nconst FILE_LOCATION_AS_IS = 0\nconst FILE_LOCATION_TRY_PARTS = 1\nconst FILE_LOCATION_TRY_P = 2\nconst FILE_LOCATION_TRY_MODELS = 3\nconst FILE_LOCATION_TRY_RELATIVE = 4\nconst FILE_LOCATION_TRY_ABSOLUTE = 5\nconst FILE_LOCATION_NOT_FOUND = 6\n\nconst MAIN_COLOUR_CODE = '16'\nconst MAIN_EDGE_COLOUR_CODE = '24'\n\nconst _tempVec0 = /* @__PURE__ */ new Vector3()\nconst _tempVec1 = /* @__PURE__ */ new Vector3()\n\nclass LDrawConditionalLineMaterial extends ShaderMaterial {\n  constructor(parameters) {\n    super({\n      uniforms: UniformsUtils.merge([\n        UniformsLib.fog,\n        {\n          diffuse: {\n            value: new Color(),\n          },\n          opacity: {\n            value: 1.0,\n          },\n        },\n      ]),\n\n      vertexShader: /* glsl */ `\n        attribute vec3 control0;\n        attribute vec3 control1;\n        attribute vec3 direction;\n        varying float discardFlag;\n\n        #include <common>\n        #include <color_pars_vertex>\n        #include <fog_pars_vertex>\n        #include <logdepthbuf_pars_vertex>\n        #include <clipping_planes_pars_vertex>\n\n        void main() {\n          #include <color_vertex>\n\n          vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);\n          gl_Position = projectionMatrix * mvPosition;\n\n          // Transform the line segment ends and control points into camera clip space\n          vec4 c0 = projectionMatrix * modelViewMatrix * vec4(control0, 1.0);\n          vec4 c1 = projectionMatrix * modelViewMatrix * vec4(control1, 1.0);\n          vec4 p0 = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n          vec4 p1 = projectionMatrix * modelViewMatrix * vec4(position + direction, 1.0);\n\n          c0.xy /= c0.w;\n          c1.xy /= c1.w;\n          p0.xy /= p0.w;\n          p1.xy /= p1.w;\n\n          // Get the direction of the segment and an orthogonal vector\n          vec2 dir = p1.xy - p0.xy;\n          vec2 norm = vec2(-dir.y, dir.x);\n\n          // Get control point directions from the line\n          vec2 c0dir = c0.xy - p1.xy;\n          vec2 c1dir = c1.xy - p1.xy;\n\n          // If the vectors to the controls points are pointed in different directions away\n          // from the line segment then the line should not be drawn.\n          float d0 = dot(normalize(norm), normalize(c0dir));\n          float d1 = dot(normalize(norm), normalize(c1dir));\n          discardFlag = float(sign(d0) != sign(d1));\n\n          #include <logdepthbuf_vertex>\n          #include <clipping_planes_vertex>\n          #include <fog_vertex>\n        }\n      `,\n\n      fragmentShader: /* glsl */ `\n        uniform vec3 diffuse;\n        uniform float opacity;\n        varying float discardFlag;\n\n        #include <common>\n        #include <color_pars_fragment>\n        #include <fog_pars_fragment>\n        #include <logdepthbuf_pars_fragment>\n        #include <clipping_planes_pars_fragment>\n\n        void main() {\n          if (discardFlag > 0.5) discard;\n\n          #include <clipping_planes_fragment>\n          vec3 outgoingLight = vec3(0.0);\n          vec4 diffuseColor = vec4(diffuse, opacity);\n          #include <logdepthbuf_fragment>\n          #include <color_fragment>\n          outgoingLight = diffuseColor.rgb; // simple shader\n          gl_FragColor = vec4(outgoingLight, diffuseColor.a);\n          #include <tonemapping_fragment>\n          #include <${version >= 154 ? 'colorspace_fragment' : 'encodings_fragment'}>\n          #include <fog_fragment>\n          #include <premultiplied_alpha_fragment>\n        }\n      `,\n    })\n\n    Object.defineProperties(this, {\n      opacity: {\n        get: function () {\n          return this.uniforms.opacity.value\n        },\n\n        set: function (value) {\n          this.uniforms.opacity.value = value\n        },\n      },\n\n      color: {\n        get: function () {\n          return this.uniforms.diffuse.value\n        },\n      },\n    })\n\n    this.setValues(parameters)\n    this.isLDrawConditionalLineMaterial = true\n  }\n}\n\nclass ConditionalLineSegments extends LineSegments {\n  constructor(geometry, material) {\n    super(geometry, material)\n    this.isConditionalLine = true\n  }\n}\n\nfunction generateFaceNormals(faces) {\n  for (let i = 0, l = faces.length; i < l; i++) {\n    const face = faces[i]\n    const vertices = face.vertices\n    const v0 = vertices[0]\n    const v1 = vertices[1]\n    const v2 = vertices[2]\n\n    _tempVec0.subVectors(v1, v0)\n    _tempVec1.subVectors(v2, v1)\n    face.faceNormal = new Vector3().crossVectors(_tempVec0, _tempVec1).normalize()\n  }\n}\n\nconst _ray = /* @__PURE__ */ new Ray()\nfunction smoothNormals(faces, lineSegments, checkSubSegments = false) {\n  // NOTE: 1e2 is pretty coarse but was chosen to quantize the resulting value because\n  // it allows edges to be smoothed as expected (see minifig arms).\n  // --\n  // And the vector values are initialize multiplied by 1 + 1e-10 to account for floating\n  // point errors on vertices along quantization boundaries. Ie after matrix multiplication\n  // vertices that should be merged might be set to \"1.7\" and \"1.6999...\" meaning they won't\n  // get merged. This added epsilon attempts to push these error values to the same quantized\n  // value for the sake of hashing. See \"AT-ST mini\" dishes. See mrdoob/three#23169.\n\n  const hashMultiplier = (1 + 1e-10) * 1e2\n  function hashVertex(v) {\n    const x = ~~(v.x * hashMultiplier)\n    const y = ~~(v.y * hashMultiplier)\n    const z = ~~(v.z * hashMultiplier)\n\n    return `${x},${y},${z}`\n  }\n\n  function hashEdge(v0, v1) {\n    return `${hashVertex(v0)}_${hashVertex(v1)}`\n  }\n\n  // converts the two vertices to a ray with a normalized direction and origin of 0, 0, 0 projected\n  // onto the original line.\n  function toNormalizedRay(v0, v1, targetRay) {\n    targetRay.direction.subVectors(v1, v0).normalize()\n\n    const scalar = v0.dot(targetRay.direction)\n    targetRay.origin.copy(v0).addScaledVector(targetRay.direction, -scalar)\n\n    return targetRay\n  }\n\n  function hashRay(ray) {\n    return hashEdge(ray.origin, ray.direction)\n  }\n\n  const hardEdges = new Set()\n  const hardEdgeRays = new Map()\n  const halfEdgeList = {}\n  const normals = []\n\n  // Save the list of hard edges by hash\n  for (let i = 0, l = lineSegments.length; i < l; i++) {\n    const ls = lineSegments[i]\n    const vertices = ls.vertices\n    const v0 = vertices[0]\n    const v1 = vertices[1]\n    hardEdges.add(hashEdge(v0, v1))\n    hardEdges.add(hashEdge(v1, v0))\n\n    // only generate the hard edge ray map if we're checking subsegments because it's more expensive to check\n    // and requires more memory.\n    if (checkSubSegments) {\n      // add both ray directions to the map\n      const ray = toNormalizedRay(v0, v1, new Ray())\n      const rh1 = hashRay(ray)\n      if (!hardEdgeRays.has(rh1)) {\n        toNormalizedRay(v1, v0, ray)\n        const rh2 = hashRay(ray)\n\n        const info = {\n          ray,\n          distances: [],\n        }\n\n        hardEdgeRays.set(rh1, info)\n        hardEdgeRays.set(rh2, info)\n      }\n\n      // store both segments ends in min, max order in the distances array to check if a face edge is a\n      // subsegment later.\n      const info = hardEdgeRays.get(rh1)\n      let d0 = info.ray.direction.dot(v0)\n      let d1 = info.ray.direction.dot(v1)\n      if (d0 > d1) {\n        ;[d0, d1] = [d1, d0]\n      }\n\n      info.distances.push(d0, d1)\n    }\n  }\n\n  // track the half edges associated with each triangle\n  for (let i = 0, l = faces.length; i < l; i++) {\n    const tri = faces[i]\n    const vertices = tri.vertices\n    const vertCount = vertices.length\n    for (let i2 = 0; i2 < vertCount; i2++) {\n      const index = i2\n      const next = (i2 + 1) % vertCount\n      const v0 = vertices[index]\n      const v1 = vertices[next]\n      const hash = hashEdge(v0, v1)\n\n      // don't add the triangle if the edge is supposed to be hard\n      if (hardEdges.has(hash)) {\n        continue\n      }\n\n      // if checking subsegments then check to see if this edge lies on a hard edge ray and whether its within any ray bounds\n      if (checkSubSegments) {\n        toNormalizedRay(v0, v1, _ray)\n\n        const rayHash = hashRay(_ray)\n        if (hardEdgeRays.has(rayHash)) {\n          const info = hardEdgeRays.get(rayHash)\n          const { ray, distances } = info\n          let d0 = ray.direction.dot(v0)\n          let d1 = ray.direction.dot(v1)\n\n          if (d0 > d1) {\n            ;[d0, d1] = [d1, d0]\n          }\n\n          // return early if the face edge is found to be a subsegment of a line edge meaning the edge will have \"hard\" normals\n          let found = false\n          for (let i = 0, l = distances.length; i < l; i += 2) {\n            if (d0 >= distances[i] && d1 <= distances[i + 1]) {\n              found = true\n              break\n            }\n          }\n\n          if (found) {\n            continue\n          }\n        }\n      }\n\n      const info = {\n        index: index,\n        tri: tri,\n      }\n      halfEdgeList[hash] = info\n    }\n  }\n\n  // Iterate until we've tried to connect all faces to share normals\n  while (true) {\n    // Stop if there are no more faces left\n    let halfEdge = null\n    for (const key in halfEdgeList) {\n      halfEdge = halfEdgeList[key]\n      break\n    }\n\n    if (halfEdge === null) {\n      break\n    }\n\n    // Exhaustively find all connected faces\n    const queue = [halfEdge]\n    while (queue.length > 0) {\n      // initialize all vertex normals in this triangle\n      const tri = queue.pop().tri\n      const vertices = tri.vertices\n      const vertNormals = tri.normals\n      const faceNormal = tri.faceNormal\n\n      // Check if any edge is connected to another triangle edge\n      const vertCount = vertices.length\n      for (let i2 = 0; i2 < vertCount; i2++) {\n        const index = i2\n        const next = (i2 + 1) % vertCount\n        const v0 = vertices[index]\n        const v1 = vertices[next]\n\n        // delete this triangle from the list so it won't be found again\n        const hash = hashEdge(v0, v1)\n        delete halfEdgeList[hash]\n\n        const reverseHash = hashEdge(v1, v0)\n        const otherInfo = halfEdgeList[reverseHash]\n        if (otherInfo) {\n          const otherTri = otherInfo.tri\n          const otherIndex = otherInfo.index\n          const otherNormals = otherTri.normals\n          const otherVertCount = otherNormals.length\n          const otherFaceNormal = otherTri.faceNormal\n\n          // NOTE: If the angle between faces is > 67.5 degrees then assume it's\n          // hard edge. There are some cases where the line segments do not line up exactly\n          // with or span multiple triangle edges (see Lunar Vehicle wheels).\n          if (Math.abs(otherTri.faceNormal.dot(tri.faceNormal)) < 0.25) {\n            continue\n          }\n\n          // if this triangle has already been traversed then it won't be in\n          // the halfEdgeList. If it has not then add it to the queue and delete\n          // it so it won't be found again.\n          if (reverseHash in halfEdgeList) {\n            queue.push(otherInfo)\n            delete halfEdgeList[reverseHash]\n          }\n\n          // share the first normal\n          const otherNext = (otherIndex + 1) % otherVertCount\n          if (vertNormals[index] && otherNormals[otherNext] && vertNormals[index] !== otherNormals[otherNext]) {\n            otherNormals[otherNext].norm.add(vertNormals[index].norm)\n            vertNormals[index].norm = otherNormals[otherNext].norm\n          }\n\n          let sharedNormal1 = vertNormals[index] || otherNormals[otherNext]\n          if (sharedNormal1 === null) {\n            // it's possible to encounter an edge of a triangle that has already been traversed meaning\n            // both edges already have different normals defined and shared. To work around this we create\n            // a wrapper object so when those edges are merged the normals can be updated everywhere.\n            sharedNormal1 = { norm: new Vector3() }\n            normals.push(sharedNormal1.norm)\n          }\n\n          if (vertNormals[index] === null) {\n            vertNormals[index] = sharedNormal1\n            sharedNormal1.norm.add(faceNormal)\n          }\n\n          if (otherNormals[otherNext] === null) {\n            otherNormals[otherNext] = sharedNormal1\n            sharedNormal1.norm.add(otherFaceNormal)\n          }\n\n          // share the second normal\n          if (vertNormals[next] && otherNormals[otherIndex] && vertNormals[next] !== otherNormals[otherIndex]) {\n            otherNormals[otherIndex].norm.add(vertNormals[next].norm)\n            vertNormals[next].norm = otherNormals[otherIndex].norm\n          }\n\n          let sharedNormal2 = vertNormals[next] || otherNormals[otherIndex]\n          if (sharedNormal2 === null) {\n            sharedNormal2 = { norm: new Vector3() }\n            normals.push(sharedNormal2.norm)\n          }\n\n          if (vertNormals[next] === null) {\n            vertNormals[next] = sharedNormal2\n            sharedNormal2.norm.add(faceNormal)\n          }\n\n          if (otherNormals[otherIndex] === null) {\n            otherNormals[otherIndex] = sharedNormal2\n            sharedNormal2.norm.add(otherFaceNormal)\n          }\n        }\n      }\n    }\n  }\n\n  // The normals of each face have been added up so now we average them by normalizing the vector.\n  for (let i = 0, l = normals.length; i < l; i++) {\n    normals[i].normalize()\n  }\n}\n\nfunction isPartType(type) {\n  return type === 'Part' || type === 'Unofficial_Part'\n}\n\nfunction isPrimitiveType(type) {\n  return /primitive/i.test(type) || type === 'Subpart'\n}\n\nclass LineParser {\n  constructor(line, lineNumber) {\n    this.line = line\n    this.lineLength = line.length\n    this.currentCharIndex = 0\n    this.currentChar = ' '\n    this.lineNumber = lineNumber\n  }\n\n  seekNonSpace() {\n    while (this.currentCharIndex < this.lineLength) {\n      this.currentChar = this.line.charAt(this.currentCharIndex)\n\n      if (this.currentChar !== ' ' && this.currentChar !== '\\t') {\n        return\n      }\n\n      this.currentCharIndex++\n    }\n  }\n\n  getToken() {\n    const pos0 = this.currentCharIndex++\n\n    // Seek space\n    while (this.currentCharIndex < this.lineLength) {\n      this.currentChar = this.line.charAt(this.currentCharIndex)\n\n      if (this.currentChar === ' ' || this.currentChar === '\\t') {\n        break\n      }\n\n      this.currentCharIndex++\n    }\n\n    const pos1 = this.currentCharIndex\n\n    this.seekNonSpace()\n\n    return this.line.substring(pos0, pos1)\n  }\n\n  getVector() {\n    return new Vector3(parseFloat(this.getToken()), parseFloat(this.getToken()), parseFloat(this.getToken()))\n  }\n\n  getRemainingString() {\n    return this.line.substring(this.currentCharIndex, this.lineLength)\n  }\n\n  isAtTheEnd() {\n    return this.currentCharIndex >= this.lineLength\n  }\n\n  setToEnd() {\n    this.currentCharIndex = this.lineLength\n  }\n\n  getLineNumberString() {\n    return this.lineNumber >= 0 ? ' at line ' + this.lineNumber : ''\n  }\n}\n\n// Fetches and parses an intermediate representation of LDraw parts files.\nclass LDrawParsedCache {\n  constructor(loader) {\n    this.loader = loader\n    this._cache = {}\n  }\n\n  cloneResult(original) {\n    const result = {}\n\n    // vertices are transformed and normals computed before being converted to geometry\n    // so these pieces must be cloned.\n    result.faces = original.faces.map((face) => {\n      return {\n        colorCode: face.colorCode,\n        material: face.material,\n        vertices: face.vertices.map((v) => v.clone()),\n        normals: face.normals.map(() => null),\n        faceNormal: null,\n      }\n    })\n\n    result.conditionalSegments = original.conditionalSegments.map((face) => {\n      return {\n        colorCode: face.colorCode,\n        material: face.material,\n        vertices: face.vertices.map((v) => v.clone()),\n        controlPoints: face.controlPoints.map((v) => v.clone()),\n      }\n    })\n\n    result.lineSegments = original.lineSegments.map((face) => {\n      return {\n        colorCode: face.colorCode,\n        material: face.material,\n        vertices: face.vertices.map((v) => v.clone()),\n      }\n    })\n\n    // none if this is subsequently modified\n    result.type = original.type\n    result.category = original.category\n    result.keywords = original.keywords\n    result.subobjects = original.subobjects\n    result.totalFaces = original.totalFaces\n    result.startingConstructionStep = original.startingConstructionStep\n    result.materials = original.materials\n    result.group = null\n    return result\n  }\n\n  async fetchData(fileName) {\n    let triedLowerCase = false\n    let locationState = FILE_LOCATION_AS_IS\n    while (locationState !== FILE_LOCATION_NOT_FOUND) {\n      let subobjectURL = fileName\n      switch (locationState) {\n        case FILE_LOCATION_AS_IS:\n          locationState = locationState + 1\n          break\n\n        case FILE_LOCATION_TRY_PARTS:\n          subobjectURL = 'parts/' + subobjectURL\n          locationState = locationState + 1\n          break\n\n        case FILE_LOCATION_TRY_P:\n          subobjectURL = 'p/' + subobjectURL\n          locationState = locationState + 1\n          break\n\n        case FILE_LOCATION_TRY_MODELS:\n          subobjectURL = 'models/' + subobjectURL\n          locationState = locationState + 1\n          break\n\n        case FILE_LOCATION_TRY_RELATIVE:\n          subobjectURL = fileName.substring(0, fileName.lastIndexOf('/') + 1) + subobjectURL\n          locationState = locationState + 1\n          break\n\n        case FILE_LOCATION_TRY_ABSOLUTE:\n          if (triedLowerCase) {\n            // Try absolute path\n            locationState = FILE_LOCATION_NOT_FOUND\n          } else {\n            // Next attempt is lower case\n            fileName = fileName.toLowerCase()\n            subobjectURL = fileName\n            triedLowerCase = true\n            locationState = FILE_LOCATION_AS_IS\n          }\n\n          break\n      }\n\n      const loader = this.loader\n      const fileLoader = new FileLoader(loader.manager)\n      fileLoader.setPath(loader.partsLibraryPath)\n      fileLoader.setRequestHeader(loader.requestHeader)\n      fileLoader.setWithCredentials(loader.withCredentials)\n\n      try {\n        const text = await fileLoader.loadAsync(subobjectURL)\n        return text\n      } catch {\n        continue\n      }\n    }\n\n    throw new Error('LDrawLoader: Subobject \"' + fileName + '\" could not be loaded.')\n  }\n\n  parse(text, fileName = null) {\n    const loader = this.loader\n\n    // final results\n    const faces = []\n    const lineSegments = []\n    const conditionalSegments = []\n    const subobjects = []\n    const materials = {}\n\n    const getLocalMaterial = (colorCode) => {\n      return materials[colorCode] || null\n    }\n\n    let type = 'Model'\n    let category = null\n    let keywords = null\n    let totalFaces = 0\n\n    // split into lines\n    if (text.indexOf('\\r\\n') !== -1) {\n      // This is faster than String.split with regex that splits on both\n      text = text.replace(/\\r\\n/g, '\\n')\n    }\n\n    const lines = text.split('\\n')\n    const numLines = lines.length\n\n    let parsingEmbeddedFiles = false\n    let currentEmbeddedFileName = null\n    let currentEmbeddedText = null\n\n    let bfcCertified = false\n    let bfcCCW = true\n    let bfcInverted = false\n    let bfcCull = true\n\n    let startingConstructionStep = false\n\n    // Parse all line commands\n    for (let lineIndex = 0; lineIndex < numLines; lineIndex++) {\n      const line = lines[lineIndex]\n\n      if (line.length === 0) continue\n\n      if (parsingEmbeddedFiles) {\n        if (line.startsWith('0 FILE ')) {\n          // Save previous embedded file in the cache\n          this.setData(currentEmbeddedFileName, currentEmbeddedText)\n\n          // New embedded text file\n          currentEmbeddedFileName = line.substring(7)\n          currentEmbeddedText = ''\n        } else {\n          currentEmbeddedText += line + '\\n'\n        }\n\n        continue\n      }\n\n      const lp = new LineParser(line, lineIndex + 1)\n      lp.seekNonSpace()\n\n      if (lp.isAtTheEnd()) {\n        // Empty line\n        continue\n      }\n\n      // Parse the line type\n      const lineType = lp.getToken()\n\n      let material\n      let colorCode\n      let segment\n      let ccw\n      let doubleSided\n      let v0, v1, v2, v3, c0, c1\n\n      switch (lineType) {\n        // Line type 0: Comment or META\n        case '0':\n          // Parse meta directive\n          const meta = lp.getToken()\n\n          if (meta) {\n            switch (meta) {\n              case '!LDRAW_ORG':\n                type = lp.getToken()\n                break\n\n              case '!COLOUR':\n                material = loader.parseColorMetaDirective(lp)\n                if (material) {\n                  materials[material.userData.code] = material\n                } else {\n                  console.warn('LDrawLoader: Error parsing material' + lp.getLineNumberString())\n                }\n\n                break\n\n              case '!CATEGORY':\n                category = lp.getToken()\n                break\n\n              case '!KEYWORDS':\n                const newKeywords = lp.getRemainingString().split(',')\n                if (newKeywords.length > 0) {\n                  if (!keywords) {\n                    keywords = []\n                  }\n\n                  newKeywords.forEach(function (keyword) {\n                    keywords.push(keyword.trim())\n                  })\n                }\n\n                break\n\n              case 'FILE':\n                if (lineIndex > 0) {\n                  // Start embedded text files parsing\n                  parsingEmbeddedFiles = true\n                  currentEmbeddedFileName = lp.getRemainingString()\n                  currentEmbeddedText = ''\n\n                  bfcCertified = false\n                  bfcCCW = true\n                }\n\n                break\n\n              case 'BFC':\n                // Changes to the backface culling state\n                while (!lp.isAtTheEnd()) {\n                  const token = lp.getToken()\n\n                  switch (token) {\n                    case 'CERTIFY':\n                    case 'NOCERTIFY':\n                      bfcCertified = token === 'CERTIFY'\n                      bfcCCW = true\n\n                      break\n\n                    case 'CW':\n                    case 'CCW':\n                      bfcCCW = token === 'CCW'\n\n                      break\n\n                    case 'INVERTNEXT':\n                      bfcInverted = true\n\n                      break\n\n                    case 'CLIP':\n                    case 'NOCLIP':\n                      bfcCull = token === 'CLIP'\n\n                      break\n\n                    default:\n                      console.warn('THREE.LDrawLoader: BFC directive \"' + token + '\" is unknown.')\n\n                      break\n                  }\n                }\n\n                break\n\n              case 'STEP':\n                startingConstructionStep = true\n\n                break\n\n              default:\n                // Other meta directives are not implemented\n                break\n            }\n          }\n\n          break\n\n        // Line type 1: Sub-object file\n        case '1':\n          colorCode = lp.getToken()\n          material = getLocalMaterial(colorCode)\n\n          const posX = parseFloat(lp.getToken())\n          const posY = parseFloat(lp.getToken())\n          const posZ = parseFloat(lp.getToken())\n          const m0 = parseFloat(lp.getToken())\n          const m1 = parseFloat(lp.getToken())\n          const m2 = parseFloat(lp.getToken())\n          const m3 = parseFloat(lp.getToken())\n          const m4 = parseFloat(lp.getToken())\n          const m5 = parseFloat(lp.getToken())\n          const m6 = parseFloat(lp.getToken())\n          const m7 = parseFloat(lp.getToken())\n          const m8 = parseFloat(lp.getToken())\n\n          const matrix = new Matrix4().set(m0, m1, m2, posX, m3, m4, m5, posY, m6, m7, m8, posZ, 0, 0, 0, 1)\n\n          let fileName = lp.getRemainingString().trim().replace(/\\\\/g, '/')\n\n          if (loader.fileMap[fileName]) {\n            // Found the subobject path in the preloaded file path map\n            fileName = loader.fileMap[fileName]\n          } else {\n            // Standardized subfolders\n            if (fileName.startsWith('s/')) {\n              fileName = 'parts/' + fileName\n            } else if (fileName.startsWith('48/')) {\n              fileName = 'p/' + fileName\n            }\n          }\n\n          subobjects.push({\n            material: material,\n            colorCode: colorCode,\n            matrix: matrix,\n            fileName: fileName,\n            inverted: bfcInverted,\n            startingConstructionStep: startingConstructionStep,\n          })\n\n          bfcInverted = false\n\n          break\n\n        // Line type 2: Line segment\n        case '2':\n          colorCode = lp.getToken()\n          material = getLocalMaterial(colorCode)\n          v0 = lp.getVector()\n          v1 = lp.getVector()\n\n          segment = {\n            material: material,\n            colorCode: colorCode,\n            vertices: [v0, v1],\n          }\n\n          lineSegments.push(segment)\n\n          break\n\n        // Line type 5: Conditional Line segment\n        case '5':\n          colorCode = lp.getToken()\n          material = getLocalMaterial(colorCode)\n          v0 = lp.getVector()\n          v1 = lp.getVector()\n          c0 = lp.getVector()\n          c1 = lp.getVector()\n\n          segment = {\n            material: material,\n            colorCode: colorCode,\n            vertices: [v0, v1],\n            controlPoints: [c0, c1],\n          }\n\n          conditionalSegments.push(segment)\n\n          break\n\n        // Line type 3: Triangle\n        case '3':\n          colorCode = lp.getToken()\n          material = getLocalMaterial(colorCode)\n          ccw = bfcCCW\n          doubleSided = !bfcCertified || !bfcCull\n\n          if (ccw === true) {\n            v0 = lp.getVector()\n            v1 = lp.getVector()\n            v2 = lp.getVector()\n          } else {\n            v2 = lp.getVector()\n            v1 = lp.getVector()\n            v0 = lp.getVector()\n          }\n\n          faces.push({\n            material: material,\n            colorCode: colorCode,\n            faceNormal: null,\n            vertices: [v0, v1, v2],\n            normals: [null, null, null],\n          })\n          totalFaces++\n\n          if (doubleSided === true) {\n            faces.push({\n              material: material,\n              colorCode: colorCode,\n              faceNormal: null,\n              vertices: [v2, v1, v0],\n              normals: [null, null, null],\n            })\n            totalFaces++\n          }\n\n          break\n\n        // Line type 4: Quadrilateral\n        case '4':\n          colorCode = lp.getToken()\n          material = getLocalMaterial(colorCode)\n          ccw = bfcCCW\n          doubleSided = !bfcCertified || !bfcCull\n\n          if (ccw === true) {\n            v0 = lp.getVector()\n            v1 = lp.getVector()\n            v2 = lp.getVector()\n            v3 = lp.getVector()\n          } else {\n            v3 = lp.getVector()\n            v2 = lp.getVector()\n            v1 = lp.getVector()\n            v0 = lp.getVector()\n          }\n\n          // specifically place the triangle diagonal in the v0 and v1 slots so we can\n          // account for the doubling of vertices later when smoothing normals.\n          faces.push({\n            material: material,\n            colorCode: colorCode,\n            faceNormal: null,\n            vertices: [v0, v1, v2, v3],\n            normals: [null, null, null, null],\n          })\n          totalFaces += 2\n\n          if (doubleSided === true) {\n            faces.push({\n              material: material,\n              colorCode: colorCode,\n              faceNormal: null,\n              vertices: [v3, v2, v1, v0],\n              normals: [null, null, null, null],\n            })\n            totalFaces += 2\n          }\n\n          break\n\n        default:\n          throw new Error('LDrawLoader: Unknown line type \"' + lineType + '\"' + lp.getLineNumberString() + '.')\n      }\n    }\n\n    if (parsingEmbeddedFiles) {\n      this.setData(currentEmbeddedFileName, currentEmbeddedText)\n    }\n\n    return {\n      faces,\n      conditionalSegments,\n      lineSegments,\n      type,\n      category,\n      keywords,\n      subobjects,\n      totalFaces,\n      startingConstructionStep,\n      materials,\n      fileName,\n      group: null,\n    }\n  }\n\n  // returns an (optionally cloned) instance of the data\n  getData(fileName, clone = true) {\n    const key = fileName.toLowerCase()\n    const result = this._cache[key]\n    if (result === null || result instanceof Promise) {\n      return null\n    }\n\n    if (clone) {\n      return this.cloneResult(result)\n    } else {\n      return result\n    }\n  }\n\n  // kicks off a fetch and parse of the requested data if it hasn't already been loaded. Returns when\n  // the data is ready to use and can be retrieved synchronously with \"getData\".\n  async ensureDataLoaded(fileName) {\n    const key = fileName.toLowerCase()\n    if (!(key in this._cache)) {\n      // replace the promise with a copy of the parsed data for immediate processing\n      this._cache[key] = this.fetchData(fileName).then((text) => {\n        const info = this.parse(text, fileName)\n        this._cache[key] = info\n        return info\n      })\n    }\n\n    await this._cache[key]\n  }\n\n  // sets the data in the cache from parsed data\n  setData(fileName, text) {\n    const key = fileName.toLowerCase()\n    this._cache[key] = this.parse(text, fileName)\n  }\n}\n\n// returns the material for an associated color code. If the color code is 16 for a face or 24 for\n// an edge then the passthroughColorCode is used.\nfunction getMaterialFromCode(colorCode, parentColorCode, materialHierarchy, forEdge) {\n  const isPassthrough = (!forEdge && colorCode === MAIN_COLOUR_CODE) || (forEdge && colorCode === MAIN_EDGE_COLOUR_CODE)\n  if (isPassthrough) {\n    colorCode = parentColorCode\n  }\n\n  return materialHierarchy[colorCode] || null\n}\n\n// Class used to parse and build LDraw parts as three.js objects and cache them if they're a \"Part\" type.\nclass LDrawPartsGeometryCache {\n  constructor(loader) {\n    this.loader = loader\n    this.parseCache = new LDrawParsedCache(loader)\n    this._cache = {}\n  }\n\n  // Convert the given file information into a mesh by processing subobjects.\n  async processIntoMesh(info) {\n    const loader = this.loader\n    const parseCache = this.parseCache\n    const faceMaterials = new Set()\n\n    // Processes the part subobject information to load child parts and merge geometry onto part\n    // piece object.\n    const processInfoSubobjects = async (info, subobject = null) => {\n      const subobjects = info.subobjects\n      const promises = []\n\n      // Trigger load of all subobjects. If a subobject isn't a primitive then load it as a separate\n      // group which lets instruction steps apply correctly.\n      for (let i = 0, l = subobjects.length; i < l; i++) {\n        const subobject = subobjects[i]\n        const promise = parseCache.ensureDataLoaded(subobject.fileName).then(() => {\n          const subobjectInfo = parseCache.getData(subobject.fileName, false)\n          if (!isPrimitiveType(subobjectInfo.type)) {\n            return this.loadModel(subobject.fileName).catch((error) => {\n              console.warn(error)\n              return null\n            })\n          }\n\n          return processInfoSubobjects(parseCache.getData(subobject.fileName), subobject)\n        })\n\n        promises.push(promise)\n      }\n\n      const group = new Group()\n      group.userData.category = info.category\n      group.userData.keywords = info.keywords\n      info.group = group\n\n      const subobjectInfos = await Promise.all(promises)\n      for (let i = 0, l = subobjectInfos.length; i < l; i++) {\n        const subobject = info.subobjects[i]\n        const subobjectInfo = subobjectInfos[i]\n\n        if (subobjectInfo === null) {\n          // the subobject failed to load\n          continue\n        }\n\n        // if the subobject was loaded as a separate group then apply the parent scopes materials\n        if (subobjectInfo.isGroup) {\n          const subobjectGroup = subobjectInfo\n          subobject.matrix.decompose(subobjectGroup.position, subobjectGroup.quaternion, subobjectGroup.scale)\n          subobjectGroup.userData.startingConstructionStep = subobject.startingConstructionStep\n          subobjectGroup.name = subobject.fileName\n\n          loader.applyMaterialsToMesh(subobjectGroup, subobject.colorCode, info.materials)\n\n          group.add(subobjectGroup)\n          continue\n        }\n\n        // add the subobject group if it has children in case it has both children and primitives\n        if (subobjectInfo.group.children.length) {\n          group.add(subobjectInfo.group)\n        }\n\n        // transform the primitives into the local space of the parent piece and append them to\n        // to the parent primitives list.\n        const parentLineSegments = info.lineSegments\n        const parentConditionalSegments = info.conditionalSegments\n        const parentFaces = info.faces\n\n        const lineSegments = subobjectInfo.lineSegments\n        const conditionalSegments = subobjectInfo.conditionalSegments\n\n        const faces = subobjectInfo.faces\n        const matrix = subobject.matrix\n        const inverted = subobject.inverted\n        const matrixScaleInverted = matrix.determinant() < 0\n        const colorCode = subobject.colorCode\n\n        const lineColorCode = colorCode === MAIN_COLOUR_CODE ? MAIN_EDGE_COLOUR_CODE : colorCode\n        for (let i = 0, l = lineSegments.length; i < l; i++) {\n          const ls = lineSegments[i]\n          const vertices = ls.vertices\n          vertices[0].applyMatrix4(matrix)\n          vertices[1].applyMatrix4(matrix)\n          ls.colorCode = ls.colorCode === MAIN_EDGE_COLOUR_CODE ? lineColorCode : ls.colorCode\n          ls.material = ls.material || getMaterialFromCode(ls.colorCode, ls.colorCode, info.materials, true)\n\n          parentLineSegments.push(ls)\n        }\n\n        for (let i = 0, l = conditionalSegments.length; i < l; i++) {\n          const os = conditionalSegments[i]\n          const vertices = os.vertices\n          const controlPoints = os.controlPoints\n          vertices[0].applyMatrix4(matrix)\n          vertices[1].applyMatrix4(matrix)\n          controlPoints[0].applyMatrix4(matrix)\n          controlPoints[1].applyMatrix4(matrix)\n          os.colorCode = os.colorCode === MAIN_EDGE_COLOUR_CODE ? lineColorCode : os.colorCode\n          os.material = os.material || getMaterialFromCode(os.colorCode, os.colorCode, info.materials, true)\n\n          parentConditionalSegments.push(os)\n        }\n\n        for (let i = 0, l = faces.length; i < l; i++) {\n          const tri = faces[i]\n          const vertices = tri.vertices\n          for (let i = 0, l = vertices.length; i < l; i++) {\n            vertices[i].applyMatrix4(matrix)\n          }\n\n          tri.colorCode = tri.colorCode === MAIN_COLOUR_CODE ? colorCode : tri.colorCode\n          tri.material = tri.material || getMaterialFromCode(tri.colorCode, colorCode, info.materials, false)\n          faceMaterials.add(tri.colorCode)\n\n          // If the scale of the object is negated then the triangle winding order\n          // needs to be flipped.\n          if (matrixScaleInverted !== inverted) {\n            vertices.reverse()\n          }\n\n          parentFaces.push(tri)\n        }\n\n        info.totalFaces += subobjectInfo.totalFaces\n      }\n\n      // Apply the parent subobjects pass through material code to this object. This is done several times due\n      // to material scoping.\n      if (subobject) {\n        loader.applyMaterialsToMesh(group, subobject.colorCode, info.materials)\n      }\n\n      return info\n    }\n\n    // Track material use to see if we need to use the normal smooth slow path for hard edges.\n    for (let i = 0, l = info.faces; i < l; i++) {\n      faceMaterials.add(info.faces[i].colorCode)\n    }\n\n    await processInfoSubobjects(info)\n\n    if (loader.smoothNormals) {\n      const checkSubSegments = faceMaterials.size > 1\n      generateFaceNormals(info.faces)\n      smoothNormals(info.faces, info.lineSegments, checkSubSegments)\n    }\n\n    // Add the primitive objects and metadata.\n    const group = info.group\n    if (info.faces.length > 0) {\n      group.add(createObject(info.faces, 3, false, info.totalFaces))\n    }\n\n    if (info.lineSegments.length > 0) {\n      group.add(createObject(info.lineSegments, 2))\n    }\n\n    if (info.conditionalSegments.length > 0) {\n      group.add(createObject(info.conditionalSegments, 2, true))\n    }\n\n    return group\n  }\n\n  hasCachedModel(fileName) {\n    return fileName !== null && fileName.toLowerCase() in this._cache\n  }\n\n  async getCachedModel(fileName) {\n    if (fileName !== null && this.hasCachedModel(fileName)) {\n      const key = fileName.toLowerCase()\n      const group = await this._cache[key]\n      return group.clone()\n    } else {\n      return null\n    }\n  }\n\n  // Loads and parses the model with the given file name. Returns a cached copy if available.\n  async loadModel(fileName) {\n    const parseCache = this.parseCache\n    const key = fileName.toLowerCase()\n    if (this.hasCachedModel(fileName)) {\n      // Return cached model if available.\n      return this.getCachedModel(fileName)\n    } else {\n      // Otherwise parse a new model.\n      // Ensure the file data is loaded and pre parsed.\n      await parseCache.ensureDataLoaded(fileName)\n\n      const info = parseCache.getData(fileName)\n      const promise = this.processIntoMesh(info)\n\n      // Now that the file has loaded it's possible that another part parse has been waiting in parallel\n      // so check the cache again to see if it's been added since the last async operation so we don't\n      // do unnecessary work.\n      if (this.hasCachedModel(fileName)) {\n        return this.getCachedModel(fileName)\n      }\n\n      // Cache object if it's a part so it can be reused later.\n      if (isPartType(info.type)) {\n        this._cache[key] = promise\n      }\n\n      // return a copy\n      const group = await promise\n      return group.clone()\n    }\n  }\n\n  // parses the given model text into a renderable object. Returns cached copy if available.\n  async parseModel(text) {\n    const parseCache = this.parseCache\n    const info = parseCache.parse(text)\n    if (isPartType(info.type) && this.hasCachedModel(info.fileName)) {\n      return this.getCachedModel(info.fileName)\n    }\n\n    return this.processIntoMesh(info)\n  }\n}\n\nfunction sortByMaterial(a, b) {\n  if (a.colorCode === b.colorCode) {\n    return 0\n  }\n\n  if (a.colorCode < b.colorCode) {\n    return -1\n  }\n\n  return 1\n}\n\nfunction createObject(elements, elementSize, isConditionalSegments = false, totalElements = null) {\n  // Creates a LineSegments (elementSize = 2) or a Mesh (elementSize = 3 )\n  // With per face / segment material, implemented with mesh groups and materials array\n\n  // Sort the faces or line segments by color code to make later the mesh groups\n  elements.sort(sortByMaterial)\n\n  if (totalElements === null) {\n    totalElements = elements.length\n  }\n\n  const positions = new Float32Array(elementSize * totalElements * 3)\n  const normals = elementSize === 3 ? new Float32Array(elementSize * totalElements * 3) : null\n  const materials = []\n\n  const quadArray = new Array(6)\n  const bufferGeometry = new BufferGeometry()\n  let prevMaterial = null\n  let index0 = 0\n  let numGroupVerts = 0\n  let offset = 0\n\n  for (let iElem = 0, nElem = elements.length; iElem < nElem; iElem++) {\n    const elem = elements[iElem]\n    let vertices = elem.vertices\n    if (vertices.length === 4) {\n      quadArray[0] = vertices[0]\n      quadArray[1] = vertices[1]\n      quadArray[2] = vertices[2]\n      quadArray[3] = vertices[0]\n      quadArray[4] = vertices[2]\n      quadArray[5] = vertices[3]\n      vertices = quadArray\n    }\n\n    for (let j = 0, l = vertices.length; j < l; j++) {\n      const v = vertices[j]\n      const index = offset + j * 3\n      positions[index + 0] = v.x\n      positions[index + 1] = v.y\n      positions[index + 2] = v.z\n    }\n\n    // create the normals array if this is a set of faces\n    if (elementSize === 3) {\n      if (!elem.faceNormal) {\n        const v0 = vertices[0]\n        const v1 = vertices[1]\n        const v2 = vertices[2]\n        _tempVec0.subVectors(v1, v0)\n        _tempVec1.subVectors(v2, v1)\n        elem.faceNormal = new Vector3().crossVectors(_tempVec0, _tempVec1).normalize()\n      }\n\n      let elemNormals = elem.normals\n      if (elemNormals.length === 4) {\n        quadArray[0] = elemNormals[0]\n        quadArray[1] = elemNormals[1]\n        quadArray[2] = elemNormals[2]\n        quadArray[3] = elemNormals[0]\n        quadArray[4] = elemNormals[2]\n        quadArray[5] = elemNormals[3]\n        elemNormals = quadArray\n      }\n\n      for (let j = 0, l = elemNormals.length; j < l; j++) {\n        // use face normal if a vertex normal is not provided\n        let n = elem.faceNormal\n        if (elemNormals[j]) {\n          n = elemNormals[j].norm\n        }\n\n        const index = offset + j * 3\n        normals[index + 0] = n.x\n        normals[index + 1] = n.y\n        normals[index + 2] = n.z\n      }\n    }\n\n    if (prevMaterial !== elem.colorCode) {\n      if (prevMaterial !== null) {\n        bufferGeometry.addGroup(index0, numGroupVerts, materials.length - 1)\n      }\n\n      const material = elem.material\n      if (material !== null) {\n        if (elementSize === 3) {\n          materials.push(material)\n        } else if (elementSize === 2) {\n          if (material !== null) {\n            if (isConditionalSegments) {\n              materials.push(material.userData.edgeMaterial.userData.conditionalEdgeMaterial)\n            } else {\n              materials.push(material.userData.edgeMaterial)\n            }\n          } else {\n            materials.push(null)\n          }\n        }\n      } else {\n        // If a material has not been made available yet then keep the color code string in the material array\n        // to save the spot for the material once a parent scopes materials are being applied to the object.\n        materials.push(elem.colorCode)\n      }\n\n      prevMaterial = elem.colorCode\n      index0 = offset / 3\n      numGroupVerts = vertices.length\n    } else {\n      numGroupVerts += vertices.length\n    }\n\n    offset += 3 * vertices.length\n  }\n\n  if (numGroupVerts > 0) {\n    bufferGeometry.addGroup(index0, Infinity, materials.length - 1)\n  }\n\n  bufferGeometry.setAttribute('position', new BufferAttribute(positions, 3))\n\n  if (normals !== null) {\n    bufferGeometry.setAttribute('normal', new BufferAttribute(normals, 3))\n  }\n\n  let object3d = null\n\n  if (elementSize === 2) {\n    if (isConditionalSegments) {\n      object3d = new ConditionalLineSegments(bufferGeometry, materials.length === 1 ? materials[0] : materials)\n    } else {\n      object3d = new LineSegments(bufferGeometry, materials.length === 1 ? materials[0] : materials)\n    }\n  } else if (elementSize === 3) {\n    object3d = new Mesh(bufferGeometry, materials.length === 1 ? materials[0] : materials)\n  }\n\n  if (isConditionalSegments) {\n    object3d.isConditionalLine = true\n\n    const controlArray0 = new Float32Array(elements.length * 3 * 2)\n    const controlArray1 = new Float32Array(elements.length * 3 * 2)\n    const directionArray = new Float32Array(elements.length * 3 * 2)\n    for (let i = 0, l = elements.length; i < l; i++) {\n      const os = elements[i]\n      const vertices = os.vertices\n      const controlPoints = os.controlPoints\n      const c0 = controlPoints[0]\n      const c1 = controlPoints[1]\n      const v0 = vertices[0]\n      const v1 = vertices[1]\n      const index = i * 3 * 2\n      controlArray0[index + 0] = c0.x\n      controlArray0[index + 1] = c0.y\n      controlArray0[index + 2] = c0.z\n      controlArray0[index + 3] = c0.x\n      controlArray0[index + 4] = c0.y\n      controlArray0[index + 5] = c0.z\n\n      controlArray1[index + 0] = c1.x\n      controlArray1[index + 1] = c1.y\n      controlArray1[index + 2] = c1.z\n      controlArray1[index + 3] = c1.x\n      controlArray1[index + 4] = c1.y\n      controlArray1[index + 5] = c1.z\n\n      directionArray[index + 0] = v1.x - v0.x\n      directionArray[index + 1] = v1.y - v0.y\n      directionArray[index + 2] = v1.z - v0.z\n      directionArray[index + 3] = v1.x - v0.x\n      directionArray[index + 4] = v1.y - v0.y\n      directionArray[index + 5] = v1.z - v0.z\n    }\n\n    bufferGeometry.setAttribute('control0', new BufferAttribute(controlArray0, 3, false))\n    bufferGeometry.setAttribute('control1', new BufferAttribute(controlArray1, 3, false))\n    bufferGeometry.setAttribute('direction', new BufferAttribute(directionArray, 3, false))\n  }\n\n  return object3d\n}\n\n//\n\nclass LDrawLoader extends Loader {\n  constructor(manager) {\n    super(manager)\n\n    // Array of THREE.Material\n    this.materials = []\n    this.materialLibrary = {}\n\n    // This also allows to handle the embedded text files (\"0 FILE\" lines)\n    this.partsCache = new LDrawPartsGeometryCache(this)\n\n    // This object is a map from file names to paths. It agilizes the paths search. If it is not set then files will be searched by trial and error.\n    this.fileMap = {}\n\n    // Initializes the materials library with default materials\n    this.setMaterials([])\n\n    // If this flag is set to true the vertex normals will be smoothed.\n    this.smoothNormals = true\n\n    // The path to load parts from the LDraw parts library from.\n    this.partsLibraryPath = ''\n  }\n\n  setPartsLibraryPath(path) {\n    this.partsLibraryPath = path\n    return this\n  }\n\n  async preloadMaterials(url) {\n    const fileLoader = new FileLoader(this.manager)\n    fileLoader.setPath(this.path)\n    fileLoader.setRequestHeader(this.requestHeader)\n    fileLoader.setWithCredentials(this.withCredentials)\n\n    const text = await fileLoader.loadAsync(url)\n    const colorLineRegex = /^0 !COLOUR/\n    const lines = text.split(/[\\n\\r]/g)\n    const materials = []\n    for (let i = 0, l = lines.length; i < l; i++) {\n      const line = lines[i]\n      if (colorLineRegex.test(line)) {\n        const directive = line.replace(colorLineRegex, '')\n        const material = this.parseColorMetaDirective(new LineParser(directive))\n        materials.push(material)\n      }\n    }\n\n    this.setMaterials(materials)\n  }\n\n  load(url, onLoad, onProgress, onError) {\n    const fileLoader = new FileLoader(this.manager)\n    fileLoader.setPath(this.path)\n    fileLoader.setRequestHeader(this.requestHeader)\n    fileLoader.setWithCredentials(this.withCredentials)\n    fileLoader.load(\n      url,\n      (text) => {\n        this.partsCache\n          .parseModel(text, this.materialLibrary)\n          .then((group) => {\n            this.applyMaterialsToMesh(group, MAIN_COLOUR_CODE, this.materialLibrary, true)\n            this.computeConstructionSteps(group)\n            onLoad(group)\n          })\n          .catch(onError)\n      },\n      onProgress,\n      onError,\n    )\n  }\n\n  parse(text, onLoad) {\n    this.partsCache.parseModel(text, this.materialLibrary).then((group) => {\n      this.computeConstructionSteps(group)\n      onLoad(group)\n    })\n  }\n\n  setMaterials(materials) {\n    this.materialLibrary = {}\n    this.materials = []\n    for (let i = 0, l = materials.length; i < l; i++) {\n      this.addMaterial(materials[i])\n    }\n\n    // Add default main triangle and line edge materials (used in pieces that can be colored with a main color)\n    this.addMaterial(this.parseColorMetaDirective(new LineParser('Main_Colour CODE 16 VALUE #FF8080 EDGE #333333')))\n    this.addMaterial(this.parseColorMetaDirective(new LineParser('Edge_Colour CODE 24 VALUE #A0A0A0 EDGE #333333')))\n\n    return this\n  }\n\n  setFileMap(fileMap) {\n    this.fileMap = fileMap\n\n    return this\n  }\n\n  addMaterial(material) {\n    // Adds a material to the material library which is on top of the parse scopes stack. And also to the materials array\n\n    const matLib = this.materialLibrary\n    if (!matLib[material.userData.code]) {\n      this.materials.push(material)\n      matLib[material.userData.code] = material\n    }\n\n    return this\n  }\n\n  getMaterial(colorCode) {\n    if (colorCode.startsWith('0x2')) {\n      // Special 'direct' material value (RGB color)\n      const color = colorCode.substring(3)\n\n      return this.parseColorMetaDirective(\n        new LineParser('Direct_Color_' + color + ' CODE -1 VALUE #' + color + ' EDGE #' + color + ''),\n      )\n    }\n\n    return this.materialLibrary[colorCode] || null\n  }\n\n  // Applies the appropriate materials to a prebuilt hierarchy of geometry. Assumes that color codes are present\n  // in the material array if they need to be filled in.\n  applyMaterialsToMesh(group, parentColorCode, materialHierarchy, finalMaterialPass = false) {\n    // find any missing materials as indicated by a color code string and replace it with a material from the current material lib\n    const loader = this\n    const parentIsPassthrough = parentColorCode === MAIN_COLOUR_CODE\n    group.traverse((c) => {\n      if (c.isMesh || c.isLineSegments) {\n        if (Array.isArray(c.material)) {\n          for (let i = 0, l = c.material.length; i < l; i++) {\n            if (!c.material[i].isMaterial) {\n              c.material[i] = getMaterial(c, c.material[i])\n            }\n          }\n        } else if (!c.material.isMaterial) {\n          c.material = getMaterial(c, c.material)\n        }\n      }\n    })\n\n    // Returns the appropriate material for the object (line or face) given color code. If the code is \"pass through\"\n    // (24 for lines, 16 for edges) then the pass through color code is used. If that is also pass through then it's\n    // simply returned for the subsequent material application.\n    function getMaterial(c, colorCode) {\n      // if our parent is a passthrough color code and we don't have the current material color available then\n      // return early.\n      if (parentIsPassthrough && !(colorCode in materialHierarchy) && !finalMaterialPass) {\n        return colorCode\n      }\n\n      const forEdge = c.isLineSegments || c.isConditionalLine\n      const isPassthrough =\n        (!forEdge && colorCode === MAIN_COLOUR_CODE) || (forEdge && colorCode === MAIN_EDGE_COLOUR_CODE)\n      if (isPassthrough) {\n        colorCode = parentColorCode\n      }\n\n      let material = null\n      if (colorCode in materialHierarchy) {\n        material = materialHierarchy[colorCode]\n      } else if (finalMaterialPass) {\n        // see if we can get the final material from from the \"getMaterial\" function which will attempt to\n        // parse the \"direct\" colors\n        material = loader.getMaterial(colorCode)\n        if (material === null) {\n          // otherwise throw an error if this is final opportunity to set the material\n          throw new Error(`LDrawLoader: Material properties for code ${colorCode} not available.`)\n        }\n      } else {\n        return colorCode\n      }\n\n      if (c.isLineSegments) {\n        material = material.userData.edgeMaterial\n\n        if (c.isConditionalLine) {\n          material = material.userData.conditionalEdgeMaterial\n        }\n      }\n\n      return material\n    }\n  }\n\n  getMainMaterial() {\n    return this.getMaterial(MAIN_COLOUR_CODE)\n  }\n\n  getMainEdgeMaterial() {\n    return this.getMaterial(MAIN_EDGE_COLOUR_CODE)\n  }\n\n  parseColorMetaDirective(lineParser) {\n    // Parses a color definition and returns a THREE.Material\n\n    let code = null\n\n    // Triangle and line colors\n    let color = 0xff00ff\n    let edgeColor = 0xff00ff\n\n    // Transparency\n    let alpha = 1\n    let isTransparent = false\n    // Self-illumination:\n    let luminance = 0\n\n    let finishType = FINISH_TYPE_DEFAULT\n\n    let edgeMaterial = null\n\n    const name = lineParser.getToken()\n    if (!name) {\n      throw new Error(\n        'LDrawLoader: Material name was expected after \"!COLOUR tag' + lineParser.getLineNumberString() + '.',\n      )\n    }\n\n    // Parse tag tokens and their parameters\n    let token = null\n    while (true) {\n      token = lineParser.getToken()\n\n      if (!token) {\n        break\n      }\n\n      switch (token.toUpperCase()) {\n        case 'CODE':\n          code = lineParser.getToken()\n          break\n\n        case 'VALUE':\n          color = lineParser.getToken()\n          if (color.startsWith('0x')) {\n            color = '#' + color.substring(2)\n          } else if (!color.startsWith('#')) {\n            throw new Error(\n              'LDrawLoader: Invalid color while parsing material' + lineParser.getLineNumberString() + '.',\n            )\n          }\n\n          break\n\n        case 'EDGE':\n          edgeColor = lineParser.getToken()\n          if (edgeColor.startsWith('0x')) {\n            edgeColor = '#' + edgeColor.substring(2)\n          } else if (!edgeColor.startsWith('#')) {\n            // Try to see if edge color is a color code\n            edgeMaterial = this.getMaterial(edgeColor)\n            if (!edgeMaterial) {\n              throw new Error(\n                'LDrawLoader: Invalid edge color while parsing material' + lineParser.getLineNumberString() + '.',\n              )\n            }\n\n            // Get the edge material for this triangle material\n            edgeMaterial = edgeMaterial.userData.edgeMaterial\n          }\n\n          break\n\n        case 'ALPHA':\n          alpha = parseInt(lineParser.getToken())\n\n          if (isNaN(alpha)) {\n            throw new Error(\n              'LDrawLoader: Invalid alpha value in material definition' + lineParser.getLineNumberString() + '.',\n            )\n          }\n\n          alpha = Math.max(0, Math.min(1, alpha / 255))\n\n          if (alpha < 1) {\n            isTransparent = true\n          }\n\n          break\n\n        case 'LUMINANCE':\n          luminance = parseInt(lineParser.getToken())\n\n          if (isNaN(luminance)) {\n            throw new Error(\n              'LDrawLoader: Invalid luminance value in material definition' + LineParser.getLineNumberString() + '.',\n            )\n          }\n\n          luminance = Math.max(0, Math.min(1, luminance / 255))\n\n          break\n\n        case 'CHROME':\n          finishType = FINISH_TYPE_CHROME\n          break\n\n        case 'PEARLESCENT':\n          finishType = FINISH_TYPE_PEARLESCENT\n          break\n\n        case 'RUBBER':\n          finishType = FINISH_TYPE_RUBBER\n          break\n\n        case 'MATTE_METALLIC':\n          finishType = FINISH_TYPE_MATTE_METALLIC\n          break\n\n        case 'METAL':\n          finishType = FINISH_TYPE_METAL\n          break\n\n        case 'MATERIAL':\n          // Not implemented\n          lineParser.setToEnd()\n          break\n\n        default:\n          throw new Error(\n            'LDrawLoader: Unknown token \"' +\n              token +\n              '\" while parsing material' +\n              lineParser.getLineNumberString() +\n              '.',\n          )\n      }\n    }\n\n    let material = null\n\n    switch (finishType) {\n      case FINISH_TYPE_DEFAULT:\n        material = new MeshStandardMaterial({ color: color, roughness: 0.3, metalness: 0 })\n        break\n\n      case FINISH_TYPE_PEARLESCENT:\n        // Try to imitate pearlescency by making the surface glossy\n        material = new MeshStandardMaterial({ color: color, roughness: 0.3, metalness: 0.25 })\n        break\n\n      case FINISH_TYPE_CHROME:\n        // Mirror finish surface\n        material = new MeshStandardMaterial({ color: color, roughness: 0, metalness: 1 })\n        break\n\n      case FINISH_TYPE_RUBBER:\n        // Rubber finish\n        material = new MeshStandardMaterial({ color: color, roughness: 0.9, metalness: 0 })\n        break\n\n      case FINISH_TYPE_MATTE_METALLIC:\n        // Brushed metal finish\n        material = new MeshStandardMaterial({ color: color, roughness: 0.8, metalness: 0.4 })\n        break\n\n      case FINISH_TYPE_METAL:\n        // Average metal finish\n        material = new MeshStandardMaterial({ color: color, roughness: 0.2, metalness: 0.85 })\n        break\n\n      default:\n        // Should not happen\n        break\n    }\n\n    material.transparent = isTransparent\n    material.premultipliedAlpha = true\n    material.opacity = alpha\n    material.depthWrite = !isTransparent\n\n    material.polygonOffset = true\n    material.polygonOffsetFactor = 1\n\n    if (luminance !== 0) {\n      material.emissive.set(material.color).multiplyScalar(luminance)\n    }\n\n    if (!edgeMaterial) {\n      // This is the material used for edges\n      edgeMaterial = new LineBasicMaterial({\n        color: edgeColor,\n        transparent: isTransparent,\n        opacity: alpha,\n        depthWrite: !isTransparent,\n      })\n      edgeMaterial.userData.code = code\n      edgeMaterial.name = name + ' - Edge'\n\n      // This is the material used for conditional edges\n      edgeMaterial.userData.conditionalEdgeMaterial = new LDrawConditionalLineMaterial({\n        fog: true,\n        transparent: isTransparent,\n        depthWrite: !isTransparent,\n        color: edgeColor,\n        opacity: alpha,\n      })\n    }\n\n    material.userData.code = code\n    material.name = name\n\n    material.userData.edgeMaterial = edgeMaterial\n\n    this.addMaterial(material)\n\n    return material\n  }\n\n  computeConstructionSteps(model) {\n    // Sets userdata.constructionStep number in Group objects and userData.numConstructionSteps number in the root Group object.\n\n    let stepNumber = 0\n\n    model.traverse((c) => {\n      if (c.isGroup) {\n        if (c.userData.startingConstructionStep) {\n          stepNumber++\n        }\n\n        c.userData.constructionStep = stepNumber\n      }\n    })\n\n    model.userData.numConstructionSteps = stepNumber + 1\n  }\n}\n\nexport { LDrawLoader }\n"],"names":["Vector3","ShaderMaterial","UniformsUtils","UniformsLib","Color","version","LineSegments","Ray","info","i","l","FileLoader","Matrix4","fileName","subobject","group","Group","BufferGeometry","BufferAttribute","Mesh","Loader","MeshStandardMaterial","LineBasicMaterial"],"mappings":"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"}