OV.Importer3dm = class extends OV.ImporterBase { constructor () { super (); this.rhino = null; } CanImportExtension (extension) { return extension === '3dm'; } GetUpDirection () { return OV.Direction.Z; } ClearContent () { this.instanceObjects = null; this.instanceDefinitions = null; } ResetContent () { this.instanceObjects = {}; this.instanceDefinitions = {}; } ImportContent (fileContent, onFinish) { if (this.rhino === null) { OV.LoadExternalLibrary ('loaders/rhino3dm.min.js').then (() => { rhino3dm ().then ((rhino) => { this.rhino = rhino; this.ImportRhinoContent (fileContent); onFinish (); }); }).catch (() => { onFinish (); }); } else { this.ImportRhinoContent (fileContent); onFinish (); } } ImportRhinoContent (fileContent) { let rhinoDoc = this.rhino.File3dm.fromByteArray (fileContent); if (rhinoDoc === null) { this.SetError ('Failed to read Rhino file.'); return; } this.ImportRhinoDocument (rhinoDoc); if (OV.IsModelEmpty (this.model)) { this.SetError ('The model doesn\'t contain any 3D meshes. Try to save the model while you are in shaded view in Rhino.'); } } ImportRhinoDocument (rhinoDoc) { this.InitRhinoInstances (rhinoDoc); this.ImportRhinoUserStrings (rhinoDoc); this.ImportRhinoGeometry (rhinoDoc); } InitRhinoInstances (rhinoDoc) { let rhinoObjects = rhinoDoc.objects (); for (let i = 0; i < rhinoObjects.count; i++) { let rhinoObject = rhinoObjects.get (i); let rhinoAttributes = rhinoObject.attributes (); if (rhinoAttributes.isInstanceDefinitionObject) { this.instanceObjects[rhinoAttributes.id] = rhinoObject; } } let rhinoInstanceDefinitions = rhinoDoc.instanceDefinitions (); for (let i = 0; i < rhinoInstanceDefinitions.count (); i++) { let rhinoInstanceDefinition = rhinoInstanceDefinitions.get (i); this.instanceDefinitions[rhinoInstanceDefinition.id] = rhinoInstanceDefinition; } } ImportRhinoUserStrings (rhinoDoc) { let docStrings = rhinoDoc.strings (); if (docStrings.count () > 0) { let propertyGroup = new OV.PropertyGroup ('Document user texts'); for (let i = 0; i < docStrings.count (); i++) { let docString = docStrings.get (i); propertyGroup.AddProperty (new OV.Property (OV.PropertyType.Text, docString[0], docString[1])); } this.model.AddPropertyGroup (propertyGroup); } } ImportRhinoGeometry (rhinoDoc) { let rhinoObjects = rhinoDoc.objects (); for (let i = 0; i < rhinoObjects.count; i++) { let rhinoObject = rhinoObjects.get (i); this.ImportRhinoGeometryObject (rhinoDoc, rhinoObject, []); } } ImportRhinoGeometryObject (rhinoDoc, rhinoObject, rhinoInstanceReferences) { let rhinoGeometry = rhinoObject.geometry (); let rhinoAttributes = rhinoObject.attributes (); let objectType = rhinoGeometry.objectType; if (rhinoAttributes.isInstanceDefinitionObject && rhinoInstanceReferences.length === 0) { return; } let rhinoMesh = null; let deleteMesh = false; if (objectType === this.rhino.ObjectType.Mesh) { rhinoMesh = rhinoGeometry; deleteMesh = false; } else if (objectType === this.rhino.ObjectType.Extrusion) { rhinoMesh = rhinoGeometry.getMesh (this.rhino.MeshType.Any); deleteMesh = true; } else if (objectType === this.rhino.ObjectType.Brep) { rhinoMesh = new this.rhino.Mesh (); let faces = rhinoGeometry.faces (); for (let i = 0; i < faces.count; i++) { let face = faces.get (i); let mesh = face.getMesh (this.rhino.MeshType.Any); if (mesh) { rhinoMesh.append (mesh); mesh.delete (); } face.delete (); } faces.delete (); rhinoMesh.compact (); deleteMesh = true; } else if (objectType === this.rhino.ObjectType.SubD) { rhinoGeometry.subdivide (3); rhinoMesh = this.rhino.Mesh.createFromSubDControlNet (rhinoGeometry); deleteMesh = true; } else if (objectType === this.rhino.ObjectType.InstanceReference) { let parentDefinitionId = rhinoGeometry.parentIdefId; let instanceDefinition = this.instanceDefinitions[parentDefinitionId]; if (instanceDefinition !== undefined) { let instanceObjectIds = instanceDefinition.getObjectIds (); for (let i = 0; i < instanceObjectIds.length; i++) { let instanceObjectId = instanceObjectIds[i]; let instanceObject = this.instanceObjects[instanceObjectId]; if (instanceObject !== undefined) { rhinoInstanceReferences.push (rhinoObject); this.ImportRhinoGeometryObject (rhinoDoc, instanceObject, rhinoInstanceReferences); rhinoInstanceReferences.pop (); } } } } if (rhinoMesh !== null) { this.ImportRhinoMesh (rhinoDoc, rhinoMesh, rhinoObject, rhinoInstanceReferences); if (deleteMesh) { rhinoMesh.delete (); } } } ImportRhinoMesh (rhinoDoc, rhinoMesh, rhinoObject, rhinoInstanceReferences) { let rhinoAttributes = rhinoObject.attributes (); let materialIndex = this.GetMaterialIndex (rhinoDoc, rhinoObject, rhinoInstanceReferences); let threeJson = rhinoMesh.toThreejsJSON (); let mesh = OV.ConvertThreeGeometryToMesh (threeJson.data, materialIndex); mesh.SetName (rhinoAttributes.name); let userStrings = rhinoAttributes.getUserStrings (); if (userStrings.length > 0) { let propertyGroup = new OV.PropertyGroup ('User texts'); for (let i = 0; i < userStrings.length; i++) { let userString = userStrings[i]; propertyGroup.AddProperty (new OV.Property (OV.PropertyType.Text, userString[0], userString[1])); } mesh.AddPropertyGroup (propertyGroup); } if (rhinoInstanceReferences.length !== 0) { let matrix = new OV.Matrix ().CreateIdentity (); for (let i = rhinoInstanceReferences.length - 1; i >= 0; i--) { let rhinoInstanceReference = rhinoInstanceReferences[i]; let rhinoInstanceReferenceGeometry = rhinoInstanceReference.geometry (); let rhinoInstanceReferenceMatrix = rhinoInstanceReferenceGeometry.xform.toFloatArray (false); let transformationMatrix = new OV.Matrix (rhinoInstanceReferenceMatrix); matrix = matrix.MultiplyMatrix (transformationMatrix); } let transformation = new OV.Transformation (matrix); OV.TransformMesh (mesh, transformation); } this.model.AddMeshToRootNode (mesh); } GetMaterialIndex (rhinoDoc, rhinoObject, rhinoInstanceReferences) { function GetRhinoMaterial (rhino, rhinoObject, rhinoInstanceReferences) { let rhinoAttributes = rhinoObject.attributes (); if (rhinoAttributes.materialSource === rhino.ObjectMaterialSource.MaterialFromObject) { let materialIndex = rhinoAttributes.materialIndex; if (materialIndex > -1) { return rhinoDoc.materials ().get (materialIndex); } } else if (rhinoAttributes.materialSource === rhino.ObjectMaterialSource.MaterialFromLayer) { let layerIndex = rhinoAttributes.layerIndex; if (layerIndex > -1) { let layer = rhinoDoc.layers ().get (layerIndex); let layerMaterialIndex = layer.renderMaterialIndex; if (layerMaterialIndex > -1) { return rhinoDoc.materials ().get (layerMaterialIndex); } } } else if (rhinoAttributes.materialSource === rhino.ObjectMaterialSource.MaterialFromParent) { if (rhinoInstanceReferences.length !== 0) { return GetRhinoMaterial (rhino, rhinoInstanceReferences[0], []); } } return null; } function FindMatchingMaterial (model, rhinoMaterial) { function SetColor (color, rhinoColor) { color.Set (rhinoColor.r, rhinoColor.g, rhinoColor.b); } function IsBlack (rhinoColor) { return rhinoColor.r === 0 && rhinoColor.g === 0 && rhinoColor.b === 0; } function IsWhite (rhinoColor) { return rhinoColor.r === 255 && rhinoColor.g === 255 && rhinoColor.b === 255; } let material = null; if (rhinoMaterial === null) { material = new OV.PhongMaterial (); material.color.Set (255, 255, 255); } else { let physicallyBased = rhinoMaterial.physicallyBased (); if (physicallyBased.supported) { material = new OV.PhysicalMaterial (); material.metalness = physicallyBased.metallic ? 1.0 : 0.0; material.roughness = physicallyBased.roughness; } else { material = new OV.PhongMaterial (); SetColor (material.ambient, rhinoMaterial.ambientColor); SetColor (material.specular, rhinoMaterial.specularColor); } material.name = rhinoMaterial.name; SetColor (material.color, rhinoMaterial.diffuseColor); material.opacity = 1.0 - rhinoMaterial.transparency; OV.UpdateMaterialTransparency (material); // material.shininess = rhinoMaterial.shine / 255.0; if (IsBlack (material.color) && !IsWhite (rhinoMaterial.reflectionColor)) { SetColor (material.color, rhinoMaterial.reflectionColor); } if (IsBlack (material.color) && !IsWhite (rhinoMaterial.transparentColor)) { SetColor (material.color, rhinoMaterial.transparentColor); } } for (let i = 0; i < model.MaterialCount (); i++) { let current = model.GetMaterial (i); if (current.IsEqual (material)) { return i; } } return model.AddMaterial (material); } let rhinoMaterial = GetRhinoMaterial (this.rhino, rhinoObject, rhinoInstanceReferences); return FindMatchingMaterial (this.model, rhinoMaterial); } };