Buckets:
| ; | |
| Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); | |
| const THREE = require("three"); | |
| const _taskCache = /* @__PURE__ */ new WeakMap(); | |
| class Rhino3dmLoader extends THREE.Loader { | |
| constructor(manager) { | |
| super(manager); | |
| this.libraryPath = ""; | |
| this.libraryPending = null; | |
| this.libraryBinary = null; | |
| this.libraryConfig = {}; | |
| this.url = ""; | |
| this.workerLimit = 4; | |
| this.workerPool = []; | |
| this.workerNextTaskID = 1; | |
| this.workerSourceURL = ""; | |
| this.workerConfig = {}; | |
| this.materials = []; | |
| } | |
| setLibraryPath(path) { | |
| this.libraryPath = path; | |
| return this; | |
| } | |
| setWorkerLimit(workerLimit) { | |
| this.workerLimit = workerLimit; | |
| return this; | |
| } | |
| load(url, onLoad, onProgress, onError) { | |
| const loader = new THREE.FileLoader(this.manager); | |
| loader.setPath(this.path); | |
| loader.setResponseType("arraybuffer"); | |
| loader.setRequestHeader(this.requestHeader); | |
| this.url = url; | |
| loader.load( | |
| url, | |
| (buffer) => { | |
| if (_taskCache.has(buffer)) { | |
| const cachedTask = _taskCache.get(buffer); | |
| return cachedTask.promise.then(onLoad).catch(onError); | |
| } | |
| this.decodeObjects(buffer, url).then(onLoad).catch(onError); | |
| }, | |
| onProgress, | |
| onError | |
| ); | |
| } | |
| debug() { | |
| console.log( | |
| "Task load: ", | |
| this.workerPool.map((worker) => worker._taskLoad) | |
| ); | |
| } | |
| decodeObjects(buffer, url) { | |
| let worker; | |
| let taskID; | |
| const taskCost = buffer.byteLength; | |
| const objectPending = this._getWorker(taskCost).then((_worker) => { | |
| worker = _worker; | |
| taskID = this.workerNextTaskID++; | |
| return new Promise((resolve, reject) => { | |
| worker._callbacks[taskID] = { resolve, reject }; | |
| worker.postMessage({ type: "decode", id: taskID, buffer }, [buffer]); | |
| }); | |
| }).then((message) => this._createGeometry(message.data)); | |
| objectPending.catch(() => true).then(() => { | |
| if (worker && taskID) { | |
| this._releaseTask(worker, taskID); | |
| } | |
| }); | |
| _taskCache.set(buffer, { | |
| url, | |
| promise: objectPending | |
| }); | |
| return objectPending; | |
| } | |
| parse(data, onLoad, onError) { | |
| this.decodeObjects(data, "").then(onLoad).catch(onError); | |
| } | |
| _compareMaterials(material) { | |
| const mat = {}; | |
| mat.name = material.name; | |
| mat.color = {}; | |
| mat.color.r = material.color.r; | |
| mat.color.g = material.color.g; | |
| mat.color.b = material.color.b; | |
| mat.type = material.type; | |
| for (let i = 0; i < this.materials.length; i++) { | |
| const m = this.materials[i]; | |
| const _mat = {}; | |
| _mat.name = m.name; | |
| _mat.color = {}; | |
| _mat.color.r = m.color.r; | |
| _mat.color.g = m.color.g; | |
| _mat.color.b = m.color.b; | |
| _mat.type = m.type; | |
| if (JSON.stringify(mat) === JSON.stringify(_mat)) { | |
| return m; | |
| } | |
| } | |
| this.materials.push(material); | |
| return material; | |
| } | |
| _createMaterial(material) { | |
| if (material === void 0) { | |
| return new THREE.MeshStandardMaterial({ | |
| color: new THREE.Color(1, 1, 1), | |
| metalness: 0.8, | |
| name: "default", | |
| side: 2 | |
| }); | |
| } | |
| const _diffuseColor = material.diffuseColor; | |
| const diffusecolor = new THREE.Color(_diffuseColor.r / 255, _diffuseColor.g / 255, _diffuseColor.b / 255); | |
| if (_diffuseColor.r === 0 && _diffuseColor.g === 0 && _diffuseColor.b === 0) { | |
| diffusecolor.r = 1; | |
| diffusecolor.g = 1; | |
| diffusecolor.b = 1; | |
| } | |
| const mat = new THREE.MeshStandardMaterial({ | |
| color: diffusecolor, | |
| name: material.name, | |
| side: 2, | |
| transparent: material.transparency > 0 ? true : false, | |
| opacity: 1 - material.transparency | |
| }); | |
| const textureLoader = new THREE.TextureLoader(); | |
| for (let i = 0; i < material.textures.length; i++) { | |
| const texture = material.textures[i]; | |
| if (texture.image !== null) { | |
| const map = textureLoader.load(texture.image); | |
| switch (texture.type) { | |
| case "Diffuse": | |
| mat.map = map; | |
| break; | |
| case "Bump": | |
| mat.bumpMap = map; | |
| break; | |
| case "Transparency": | |
| mat.alphaMap = map; | |
| mat.transparent = true; | |
| break; | |
| case "Emap": | |
| mat.envMap = map; | |
| break; | |
| } | |
| } | |
| } | |
| return mat; | |
| } | |
| _createGeometry(data) { | |
| const object = new THREE.Object3D(); | |
| const instanceDefinitionObjects = []; | |
| const instanceDefinitions = []; | |
| const instanceReferences = []; | |
| object.userData["layers"] = data.layers; | |
| object.userData["groups"] = data.groups; | |
| object.userData["settings"] = data.settings; | |
| object.userData["objectType"] = "File3dm"; | |
| object.userData["materials"] = null; | |
| object.name = this.url; | |
| let objects = data.objects; | |
| const materials = data.materials; | |
| for (let i = 0; i < objects.length; i++) { | |
| const obj = objects[i]; | |
| const attributes = obj.attributes; | |
| switch (obj.objectType) { | |
| case "InstanceDefinition": | |
| instanceDefinitions.push(obj); | |
| break; | |
| case "InstanceReference": | |
| instanceReferences.push(obj); | |
| break; | |
| default: | |
| let _object; | |
| if (attributes.materialIndex >= 0) { | |
| const rMaterial = materials[attributes.materialIndex]; | |
| let material = this._createMaterial(rMaterial); | |
| material = this._compareMaterials(material); | |
| _object = this._createObject(obj, material); | |
| } else { | |
| const material = this._createMaterial(); | |
| _object = this._createObject(obj, material); | |
| } | |
| if (_object === void 0) { | |
| continue; | |
| } | |
| const layer = data.layers[attributes.layerIndex]; | |
| _object.visible = layer ? data.layers[attributes.layerIndex].visible : true; | |
| if (attributes.isInstanceDefinitionObject) { | |
| instanceDefinitionObjects.push(_object); | |
| } else { | |
| object.add(_object); | |
| } | |
| break; | |
| } | |
| } | |
| for (let i = 0; i < instanceDefinitions.length; i++) { | |
| const iDef = instanceDefinitions[i]; | |
| objects = []; | |
| for (let j = 0; j < iDef.attributes.objectIds.length; j++) { | |
| const objId = iDef.attributes.objectIds[j]; | |
| for (let p = 0; p < instanceDefinitionObjects.length; p++) { | |
| const idoId = instanceDefinitionObjects[p].userData.attributes.id; | |
| if (objId === idoId) { | |
| objects.push(instanceDefinitionObjects[p]); | |
| } | |
| } | |
| } | |
| for (let j = 0; j < instanceReferences.length; j++) { | |
| const iRef = instanceReferences[j]; | |
| if (iRef.geometry.parentIdefId === iDef.attributes.id) { | |
| const iRefObject = new THREE.Object3D(); | |
| const xf = iRef.geometry.xform.array; | |
| const matrix = new THREE.Matrix4(); | |
| matrix.set( | |
| xf[0], | |
| xf[1], | |
| xf[2], | |
| xf[3], | |
| xf[4], | |
| xf[5], | |
| xf[6], | |
| xf[7], | |
| xf[8], | |
| xf[9], | |
| xf[10], | |
| xf[11], | |
| xf[12], | |
| xf[13], | |
| xf[14], | |
| xf[15] | |
| ); | |
| iRefObject.applyMatrix4(matrix); | |
| for (let p = 0; p < objects.length; p++) { | |
| iRefObject.add(objects[p].clone(true)); | |
| } | |
| object.add(iRefObject); | |
| } | |
| } | |
| } | |
| object.userData["materials"] = this.materials; | |
| return object; | |
| } | |
| _createObject(obj, mat) { | |
| const loader = new THREE.BufferGeometryLoader(); | |
| const attributes = obj.attributes; | |
| let geometry, material, _color, color; | |
| switch (obj.objectType) { | |
| case "Point": | |
| case "PointSet": | |
| geometry = loader.parse(obj.geometry); | |
| if (geometry.attributes.hasOwnProperty("color")) { | |
| material = new THREE.PointsMaterial({ vertexColors: true, sizeAttenuation: false, size: 2 }); | |
| } else { | |
| _color = attributes.drawColor; | |
| color = new THREE.Color(_color.r / 255, _color.g / 255, _color.b / 255); | |
| material = new THREE.PointsMaterial({ color, sizeAttenuation: false, size: 2 }); | |
| } | |
| material = this._compareMaterials(material); | |
| const points = new THREE.Points(geometry, material); | |
| points.userData["attributes"] = attributes; | |
| points.userData["objectType"] = obj.objectType; | |
| if (attributes.name) { | |
| points.name = attributes.name; | |
| } | |
| return points; | |
| case "Mesh": | |
| case "Extrusion": | |
| case "SubD": | |
| case "Brep": | |
| if (obj.geometry === null) | |
| return; | |
| geometry = loader.parse(obj.geometry); | |
| if (geometry.attributes.hasOwnProperty("color")) { | |
| mat.vertexColors = true; | |
| } | |
| if (mat === null) { | |
| mat = this._createMaterial(); | |
| mat = this._compareMaterials(mat); | |
| } | |
| const mesh = new THREE.Mesh(geometry, mat); | |
| mesh.castShadow = attributes.castsShadows; | |
| mesh.receiveShadow = attributes.receivesShadows; | |
| mesh.userData["attributes"] = attributes; | |
| mesh.userData["objectType"] = obj.objectType; | |
| if (attributes.name) { | |
| mesh.name = attributes.name; | |
| } | |
| return mesh; | |
| case "Curve": | |
| geometry = loader.parse(obj.geometry); | |
| _color = attributes.drawColor; | |
| color = new THREE.Color(_color.r / 255, _color.g / 255, _color.b / 255); | |
| material = new THREE.LineBasicMaterial({ color }); | |
| material = this._compareMaterials(material); | |
| const lines = new THREE.Line(geometry, material); | |
| lines.userData["attributes"] = attributes; | |
| lines.userData["objectType"] = obj.objectType; | |
| if (attributes.name) { | |
| lines.name = attributes.name; | |
| } | |
| return lines; | |
| case "TextDot": | |
| geometry = obj.geometry; | |
| const ctx = document.createElement("canvas").getContext("2d"); | |
| const font = `${geometry.fontHeight}px ${geometry.fontFace}`; | |
| ctx.font = font; | |
| const width = ctx.measureText(geometry.text).width + 10; | |
| const height = geometry.fontHeight + 10; | |
| const r = window.devicePixelRatio; | |
| ctx.canvas.width = width * r; | |
| ctx.canvas.height = height * r; | |
| ctx.canvas.style.width = width + "px"; | |
| ctx.canvas.style.height = height + "px"; | |
| ctx.setTransform(r, 0, 0, r, 0, 0); | |
| ctx.font = font; | |
| ctx.textBaseline = "middle"; | |
| ctx.textAlign = "center"; | |
| color = attributes.drawColor; | |
| ctx.fillStyle = `rgba(${color.r},${color.g},${color.b},${color.a})`; | |
| ctx.fillRect(0, 0, width, height); | |
| ctx.fillStyle = "white"; | |
| ctx.fillText(geometry.text, width / 2, height / 2); | |
| const texture = new THREE.CanvasTexture(ctx.canvas); | |
| texture.minFilter = THREE.LinearFilter; | |
| texture.wrapS = THREE.ClampToEdgeWrapping; | |
| texture.wrapT = THREE.ClampToEdgeWrapping; | |
| material = new THREE.SpriteMaterial({ map: texture, depthTest: false }); | |
| const sprite = new THREE.Sprite(material); | |
| sprite.position.set(geometry.point[0], geometry.point[1], geometry.point[2]); | |
| sprite.scale.set(width / 10, height / 10, 1); | |
| sprite.userData["attributes"] = attributes; | |
| sprite.userData["objectType"] = obj.objectType; | |
| if (attributes.name) { | |
| sprite.name = attributes.name; | |
| } | |
| return sprite; | |
| case "Light": | |
| geometry = obj.geometry; | |
| let light; | |
| if (geometry.isDirectionalLight) { | |
| light = new THREE.DirectionalLight(); | |
| light.castShadow = attributes.castsShadows; | |
| light.position.set(geometry.location[0], geometry.location[1], geometry.location[2]); | |
| light.target.position.set(geometry.direction[0], geometry.direction[1], geometry.direction[2]); | |
| light.shadow.normalBias = 0.1; | |
| } else if (geometry.isPointLight) { | |
| light = new THREE.PointLight(); | |
| light.castShadow = attributes.castsShadows; | |
| light.position.set(geometry.location[0], geometry.location[1], geometry.location[2]); | |
| light.shadow.normalBias = 0.1; | |
| } else if (geometry.isRectangularLight) { | |
| light = new THREE.RectAreaLight(); | |
| const width2 = Math.abs(geometry.width[2]); | |
| const height2 = Math.abs(geometry.length[0]); | |
| light.position.set(geometry.location[0] - height2 / 2, geometry.location[1], geometry.location[2] - width2 / 2); | |
| light.height = height2; | |
| light.width = width2; | |
| light.lookAt(new THREE.Vector3(geometry.direction[0], geometry.direction[1], geometry.direction[2])); | |
| } else if (geometry.isSpotLight) { | |
| light = new THREE.SpotLight(); | |
| light.castShadow = attributes.castsShadows; | |
| light.position.set(geometry.location[0], geometry.location[1], geometry.location[2]); | |
| light.target.position.set(geometry.direction[0], geometry.direction[1], geometry.direction[2]); | |
| light.angle = geometry.spotAngleRadians; | |
| light.shadow.normalBias = 0.1; | |
| } else if (geometry.isLinearLight) { | |
| console.warn("THREE.3DMLoader: No conversion exists for linear lights."); | |
| return; | |
| } | |
| if (light) { | |
| light.intensity = geometry.intensity; | |
| _color = geometry.diffuse; | |
| color = new THREE.Color(_color.r / 255, _color.g / 255, _color.b / 255); | |
| light.color = color; | |
| light.userData["attributes"] = attributes; | |
| light.userData["objectType"] = obj.objectType; | |
| } | |
| return light; | |
| } | |
| } | |
| _initLibrary() { | |
| if (!this.libraryPending) { | |
| const jsLoader = new THREE.FileLoader(this.manager); | |
| jsLoader.setPath(this.libraryPath); | |
| const jsContent = new Promise((resolve, reject) => { | |
| jsLoader.load("rhino3dm.js", resolve, void 0, reject); | |
| }); | |
| const binaryLoader = new THREE.FileLoader(this.manager); | |
| binaryLoader.setPath(this.libraryPath); | |
| binaryLoader.setResponseType("arraybuffer"); | |
| const binaryContent = new Promise((resolve, reject) => { | |
| binaryLoader.load("rhino3dm.wasm", resolve, void 0, reject); | |
| }); | |
| this.libraryPending = Promise.all([jsContent, binaryContent]).then(([jsContent2, binaryContent2]) => { | |
| this.libraryConfig.wasmBinary = binaryContent2; | |
| const fn = Rhino3dmWorker.toString(); | |
| const body = [ | |
| "/* rhino3dm.js */", | |
| jsContent2, | |
| "/* worker */", | |
| fn.substring(fn.indexOf("{") + 1, fn.lastIndexOf("}")) | |
| ].join("\n"); | |
| this.workerSourceURL = URL.createObjectURL(new Blob([body])); | |
| }); | |
| } | |
| return this.libraryPending; | |
| } | |
| _getWorker(taskCost) { | |
| return this._initLibrary().then(() => { | |
| if (this.workerPool.length < this.workerLimit) { | |
| const worker2 = new Worker(this.workerSourceURL); | |
| worker2._callbacks = {}; | |
| worker2._taskCosts = {}; | |
| worker2._taskLoad = 0; | |
| worker2.postMessage({ | |
| type: "init", | |
| libraryConfig: this.libraryConfig | |
| }); | |
| worker2.onmessage = function(e) { | |
| const message = e.data; | |
| switch (message.type) { | |
| case "decode": | |
| worker2._callbacks[message.id].resolve(message); | |
| break; | |
| case "error": | |
| worker2._callbacks[message.id].reject(message); | |
| break; | |
| default: | |
| console.error('THREE.Rhino3dmLoader: Unexpected message, "' + message.type + '"'); | |
| } | |
| }; | |
| this.workerPool.push(worker2); | |
| } else { | |
| this.workerPool.sort(function(a, b) { | |
| return a._taskLoad > b._taskLoad ? -1 : 1; | |
| }); | |
| } | |
| const worker = this.workerPool[this.workerPool.length - 1]; | |
| worker._taskLoad += taskCost; | |
| return worker; | |
| }); | |
| } | |
| _releaseTask(worker, taskID) { | |
| worker._taskLoad -= worker._taskCosts[taskID]; | |
| delete worker._callbacks[taskID]; | |
| delete worker._taskCosts[taskID]; | |
| } | |
| dispose() { | |
| for (let i = 0; i < this.workerPool.length; ++i) { | |
| this.workerPool[i].terminate(); | |
| } | |
| this.workerPool.length = 0; | |
| return this; | |
| } | |
| } | |
| function Rhino3dmWorker() { | |
| let libraryPending; | |
| let libraryConfig; | |
| let rhino; | |
| onmessage = function(e) { | |
| const message = e.data; | |
| switch (message.type) { | |
| case "init": | |
| libraryConfig = message.libraryConfig; | |
| const wasmBinary = libraryConfig.wasmBinary; | |
| let RhinoModule; | |
| libraryPending = new Promise(function(resolve) { | |
| RhinoModule = { wasmBinary, onRuntimeInitialized: resolve }; | |
| rhino3dm(RhinoModule); | |
| }).then(() => { | |
| rhino = RhinoModule; | |
| }); | |
| break; | |
| case "decode": | |
| const buffer = message.buffer; | |
| libraryPending.then(() => { | |
| const data = decodeObjects(rhino, buffer); | |
| self.postMessage({ type: "decode", id: message.id, data }); | |
| }); | |
| break; | |
| } | |
| }; | |
| function decodeObjects(rhino2, buffer) { | |
| const arr = new Uint8Array(buffer); | |
| const doc = rhino2.File3dm.fromByteArray(arr); | |
| const objects = []; | |
| const materials = []; | |
| const layers = []; | |
| const views = []; | |
| const namedViews = []; | |
| const groups = []; | |
| const objs = doc.objects(); | |
| const cnt = objs.count; | |
| for (let i = 0; i < cnt; i++) { | |
| const _object = objs.get(i); | |
| const object = extractObjectData(_object, doc); | |
| _object.delete(); | |
| if (object) { | |
| objects.push(object); | |
| } | |
| } | |
| for (let i = 0; i < doc.instanceDefinitions().count(); i++) { | |
| const idef = doc.instanceDefinitions().get(i); | |
| const idefAttributes = extractProperties(idef); | |
| idefAttributes.objectIds = idef.getObjectIds(); | |
| objects.push({ geometry: null, attributes: idefAttributes, objectType: "InstanceDefinition" }); | |
| } | |
| const textureTypes = [ | |
| // rhino.TextureType.Bitmap, | |
| rhino2.TextureType.Diffuse, | |
| rhino2.TextureType.Bump, | |
| rhino2.TextureType.Transparency, | |
| rhino2.TextureType.Opacity, | |
| rhino2.TextureType.Emap | |
| ]; | |
| const pbrTextureTypes = [ | |
| rhino2.TextureType.PBR_BaseColor, | |
| rhino2.TextureType.PBR_Subsurface, | |
| rhino2.TextureType.PBR_SubsurfaceScattering, | |
| rhino2.TextureType.PBR_SubsurfaceScatteringRadius, | |
| rhino2.TextureType.PBR_Metallic, | |
| rhino2.TextureType.PBR_Specular, | |
| rhino2.TextureType.PBR_SpecularTint, | |
| rhino2.TextureType.PBR_Roughness, | |
| rhino2.TextureType.PBR_Anisotropic, | |
| rhino2.TextureType.PBR_Anisotropic_Rotation, | |
| rhino2.TextureType.PBR_Sheen, | |
| rhino2.TextureType.PBR_SheenTint, | |
| rhino2.TextureType.PBR_Clearcoat, | |
| rhino2.TextureType.PBR_ClearcoatBump, | |
| rhino2.TextureType.PBR_ClearcoatRoughness, | |
| rhino2.TextureType.PBR_OpacityIor, | |
| rhino2.TextureType.PBR_OpacityRoughness, | |
| rhino2.TextureType.PBR_Emission, | |
| rhino2.TextureType.PBR_AmbientOcclusion, | |
| rhino2.TextureType.PBR_Displacement | |
| ]; | |
| for (let i = 0; i < doc.materials().count(); i++) { | |
| const _material = doc.materials().get(i); | |
| const _pbrMaterial = _material.physicallyBased(); | |
| let material = extractProperties(_material); | |
| const textures = []; | |
| for (let j = 0; j < textureTypes.length; j++) { | |
| const _texture = _material.getTexture(textureTypes[j]); | |
| if (_texture) { | |
| let textureType = textureTypes[j].constructor.name; | |
| textureType = textureType.substring(12, textureType.length); | |
| const texture = { type: textureType }; | |
| const image = doc.getEmbeddedFileAsBase64(_texture.fileName); | |
| if (image) { | |
| texture.image = "data:image/png;base64," + image; | |
| } else { | |
| console.warn(`THREE.3DMLoader: Image for ${textureType} texture not embedded in file.`); | |
| texture.image = null; | |
| } | |
| textures.push(texture); | |
| _texture.delete(); | |
| } | |
| } | |
| material.textures = textures; | |
| if (_pbrMaterial.supported) { | |
| console.log("pbr true"); | |
| for (let j = 0; j < pbrTextureTypes.length; j++) { | |
| const _texture = _material.getTexture(textureTypes[j]); | |
| if (_texture) { | |
| const image = doc.getEmbeddedFileAsBase64(_texture.fileName); | |
| let textureType = textureTypes[j].constructor.name; | |
| textureType = textureType.substring(12, textureType.length); | |
| const texture = { type: textureType, image: "data:image/png;base64," + image }; | |
| textures.push(texture); | |
| _texture.delete(); | |
| } | |
| } | |
| const pbMaterialProperties = extractProperties(_material.physicallyBased()); | |
| material = Object.assign(pbMaterialProperties, material); | |
| } | |
| materials.push(material); | |
| _material.delete(); | |
| _pbrMaterial.delete(); | |
| } | |
| for (let i = 0; i < doc.layers().count(); i++) { | |
| const _layer = doc.layers().get(i); | |
| const layer = extractProperties(_layer); | |
| layers.push(layer); | |
| _layer.delete(); | |
| } | |
| for (let i = 0; i < doc.views().count(); i++) { | |
| const _view = doc.views().get(i); | |
| const view = extractProperties(_view); | |
| views.push(view); | |
| _view.delete(); | |
| } | |
| for (let i = 0; i < doc.namedViews().count(); i++) { | |
| const _namedView = doc.namedViews().get(i); | |
| const namedView = extractProperties(_namedView); | |
| namedViews.push(namedView); | |
| _namedView.delete(); | |
| } | |
| for (let i = 0; i < doc.groups().count(); i++) { | |
| const _group = doc.groups().get(i); | |
| const group = extractProperties(_group); | |
| groups.push(group); | |
| _group.delete(); | |
| } | |
| const settings = extractProperties(doc.settings()); | |
| doc.delete(); | |
| return { objects, materials, layers, views, namedViews, groups, settings }; | |
| } | |
| function extractObjectData(object, doc) { | |
| const _geometry = object.geometry(); | |
| const _attributes = object.attributes(); | |
| let objectType = _geometry.objectType; | |
| let geometry, attributes, position, data, mesh; | |
| switch (objectType) { | |
| case rhino.ObjectType.Curve: | |
| const pts = curveToPoints(_geometry, 100); | |
| position = {}; | |
| attributes = {}; | |
| data = {}; | |
| position.itemSize = 3; | |
| position.type = "Float32Array"; | |
| position.array = []; | |
| for (let j = 0; j < pts.length; j++) { | |
| position.array.push(pts[j][0]); | |
| position.array.push(pts[j][1]); | |
| position.array.push(pts[j][2]); | |
| } | |
| attributes.position = position; | |
| data.attributes = attributes; | |
| geometry = { data }; | |
| break; | |
| case rhino.ObjectType.Point: | |
| const pt = _geometry.location; | |
| position = {}; | |
| const color = {}; | |
| attributes = {}; | |
| data = {}; | |
| position.itemSize = 3; | |
| position.type = "Float32Array"; | |
| position.array = [pt[0], pt[1], pt[2]]; | |
| const _color = _attributes.drawColor(doc); | |
| color.itemSize = 3; | |
| color.type = "Float32Array"; | |
| color.array = [_color.r / 255, _color.g / 255, _color.b / 255]; | |
| attributes.position = position; | |
| attributes.color = color; | |
| data.attributes = attributes; | |
| geometry = { data }; | |
| break; | |
| case rhino.ObjectType.PointSet: | |
| case rhino.ObjectType.Mesh: | |
| geometry = _geometry.toThreejsJSON(); | |
| break; | |
| case rhino.ObjectType.Brep: | |
| const faces = _geometry.faces(); | |
| mesh = new rhino.Mesh(); | |
| for (let faceIndex = 0; faceIndex < faces.count; faceIndex++) { | |
| const face = faces.get(faceIndex); | |
| const _mesh = face.getMesh(rhino.MeshType.Any); | |
| if (_mesh) { | |
| mesh.append(_mesh); | |
| _mesh.delete(); | |
| } | |
| face.delete(); | |
| } | |
| if (mesh.faces().count > 0) { | |
| mesh.compact(); | |
| geometry = mesh.toThreejsJSON(); | |
| faces.delete(); | |
| } | |
| mesh.delete(); | |
| break; | |
| case rhino.ObjectType.Extrusion: | |
| mesh = _geometry.getMesh(rhino.MeshType.Any); | |
| if (mesh) { | |
| geometry = mesh.toThreejsJSON(); | |
| mesh.delete(); | |
| } | |
| break; | |
| case rhino.ObjectType.TextDot: | |
| geometry = extractProperties(_geometry); | |
| break; | |
| case rhino.ObjectType.Light: | |
| geometry = extractProperties(_geometry); | |
| break; | |
| case rhino.ObjectType.InstanceReference: | |
| geometry = extractProperties(_geometry); | |
| geometry.xform = extractProperties(_geometry.xform); | |
| geometry.xform.array = _geometry.xform.toFloatArray(true); | |
| break; | |
| case rhino.ObjectType.SubD: | |
| _geometry.subdivide(3); | |
| mesh = rhino.Mesh.createFromSubDControlNet(_geometry); | |
| if (mesh) { | |
| geometry = mesh.toThreejsJSON(); | |
| mesh.delete(); | |
| } | |
| break; | |
| default: | |
| console.warn(`THREE.3DMLoader: TODO: Implement ${objectType.constructor.name}`); | |
| break; | |
| } | |
| if (geometry) { | |
| attributes = extractProperties(_attributes); | |
| attributes.geometry = extractProperties(_geometry); | |
| if (_attributes.groupCount > 0) { | |
| attributes.groupIds = _attributes.getGroupList(); | |
| } | |
| if (_attributes.userStringCount > 0) { | |
| attributes.userStrings = _attributes.getUserStrings(); | |
| } | |
| if (_geometry.userStringCount > 0) { | |
| attributes.geometry.userStrings = _geometry.getUserStrings(); | |
| } | |
| attributes.drawColor = _attributes.drawColor(doc); | |
| objectType = objectType.constructor.name; | |
| objectType = objectType.substring(11, objectType.length); | |
| return { geometry, attributes, objectType }; | |
| } else { | |
| console.warn(`THREE.3DMLoader: ${objectType.constructor.name} has no associated mesh geometry.`); | |
| } | |
| } | |
| function extractProperties(object) { | |
| const result = {}; | |
| for (const property in object) { | |
| const value = object[property]; | |
| if (typeof value !== "function") { | |
| if (typeof value === "object" && value !== null && value.hasOwnProperty("constructor")) { | |
| result[property] = { name: value.constructor.name, value: value.value }; | |
| } else { | |
| result[property] = value; | |
| } | |
| } | |
| } | |
| return result; | |
| } | |
| function curveToPoints(curve, pointLimit) { | |
| let pointCount = pointLimit; | |
| let rc = []; | |
| const ts = []; | |
| if (curve instanceof rhino.LineCurve) { | |
| return [curve.pointAtStart, curve.pointAtEnd]; | |
| } | |
| if (curve instanceof rhino.PolylineCurve) { | |
| pointCount = curve.pointCount; | |
| for (let i = 0; i < pointCount; i++) { | |
| rc.push(curve.point(i)); | |
| } | |
| return rc; | |
| } | |
| if (curve instanceof rhino.PolyCurve) { | |
| const segmentCount = curve.segmentCount; | |
| for (let i = 0; i < segmentCount; i++) { | |
| const segment = curve.segmentCurve(i); | |
| const segmentArray = curveToPoints(segment, pointCount); | |
| rc = rc.concat(segmentArray); | |
| segment.delete(); | |
| } | |
| return rc; | |
| } | |
| if (curve instanceof rhino.ArcCurve) { | |
| pointCount = Math.floor(curve.angleDegrees / 5); | |
| pointCount = pointCount < 2 ? 2 : pointCount; | |
| } | |
| if (curve instanceof rhino.NurbsCurve && curve.degree === 1) { | |
| const pLine = curve.tryGetPolyline(); | |
| for (let i = 0; i < pLine.count; i++) { | |
| rc.push(pLine.get(i)); | |
| } | |
| pLine.delete(); | |
| return rc; | |
| } | |
| const domain = curve.domain; | |
| const divisions = pointCount - 1; | |
| for (let j = 0; j < pointCount; j++) { | |
| const t = domain[0] + j / divisions * (domain[1] - domain[0]); | |
| if (t === domain[0] || t === domain[1]) { | |
| ts.push(t); | |
| continue; | |
| } | |
| const tan = curve.tangentAt(t); | |
| const prevTan = curve.tangentAt(ts.slice(-1)[0]); | |
| const tS = tan[0] * tan[0] + tan[1] * tan[1] + tan[2] * tan[2]; | |
| const ptS = prevTan[0] * prevTan[0] + prevTan[1] * prevTan[1] + prevTan[2] * prevTan[2]; | |
| const denominator = Math.sqrt(tS * ptS); | |
| let angle; | |
| if (denominator === 0) { | |
| angle = Math.PI / 2; | |
| } else { | |
| const theta = (tan.x * prevTan.x + tan.y * prevTan.y + tan.z * prevTan.z) / denominator; | |
| angle = Math.acos(Math.max(-1, Math.min(1, theta))); | |
| } | |
| if (angle < 0.1) | |
| continue; | |
| ts.push(t); | |
| } | |
| rc = ts.map((t) => curve.pointAt(t)); | |
| return rc; | |
| } | |
| } | |
| exports.Rhino3dmLoader = Rhino3dmLoader; | |
| //# sourceMappingURL=3DMLoader.cjs.map | |
Xet Storage Details
- Size:
- 28.7 kB
- Xet hash:
- f2a973b6b1484fb6e3e5f0554715f7bfad952d3d24ae2d662996c42f872f07b8
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.