331 lines
9.9 KiB
JavaScript
331 lines
9.9 KiB
JavaScript
OV.Importer3dm = class extends OV.ImporterBase
|
|
{
|
|
constructor ()
|
|
{
|
|
super ();
|
|
this.rhino = null;
|
|
}
|
|
|
|
CanImportExtension (extension)
|
|
{
|
|
return extension === '3dm';
|
|
}
|
|
|
|
GetKnownFileFormats ()
|
|
{
|
|
return {
|
|
'3dm' : OV.FileFormat.Binary
|
|
};
|
|
}
|
|
|
|
GetUpDirection ()
|
|
{
|
|
return OV.Direction.Z;
|
|
}
|
|
|
|
ClearContent ()
|
|
{
|
|
this.instanceObjects = null;
|
|
this.instanceDefinitions = null;
|
|
}
|
|
|
|
ResetContent ()
|
|
{
|
|
this.instanceObjects = {};
|
|
this.instanceDefinitions = {};
|
|
}
|
|
|
|
ImportContent (fileContent, onFinish)
|
|
{
|
|
if (this.rhino === null) {
|
|
let obj = this;
|
|
OV.LoadExternalLibrary ('rhino3dm.min.js', {
|
|
success : function () {
|
|
rhino3dm ().then (function (rhino) {
|
|
obj.rhino = rhino;
|
|
obj.ImportRhinoContent (fileContent);
|
|
onFinish ();
|
|
});
|
|
},
|
|
error : function () {
|
|
onFinish ();
|
|
}
|
|
});
|
|
} else {
|
|
this.ImportRhinoContent (fileContent);
|
|
onFinish ();
|
|
}
|
|
}
|
|
|
|
ImportRhinoContent (fileContent)
|
|
{
|
|
let rhinoDoc = this.rhino.File3dm.fromByteArray (fileContent);
|
|
if (rhinoDoc === null) {
|
|
this.SetError ();
|
|
this.SetMessage ('Failed to read Rhino file.');
|
|
return;
|
|
}
|
|
this.ImportRhinoDocument (rhinoDoc);
|
|
if (OV.IsModelEmpty (this.model)) {
|
|
this.SetError ();
|
|
this.SetMessage ('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.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;
|
|
}
|
|
}
|
|
|
|
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 mesh = new OV.Mesh ();
|
|
mesh.SetName (rhinoAttributes.name);
|
|
|
|
let materialIndex = this.GetMaterialIndex (rhinoDoc, rhinoObject, rhinoInstanceReferences);
|
|
let threeJson = rhinoMesh.toThreejsJSON ();
|
|
let vertices = threeJson.data.attributes.position.array;
|
|
for (let i = 0; i < vertices.length; i += 3) {
|
|
let x = vertices[i];
|
|
let y = vertices[i + 1];
|
|
let z = vertices[i + 2];
|
|
mesh.AddVertex (new OV.Coord3D (x, y, z));
|
|
}
|
|
let hasNormals = (threeJson.data.attributes.normal !== undefined);
|
|
if (hasNormals) {
|
|
let normals = threeJson.data.attributes.normal.array;
|
|
for (let i = 0; i < normals.length; i += 3) {
|
|
let x = normals[i];
|
|
let y = normals[i + 1];
|
|
let z = normals[i + 2];
|
|
mesh.AddNormal (new OV.Coord3D (x, y, z));
|
|
}
|
|
}
|
|
let hasUVs = (threeJson.data.attributes.uv !== undefined);
|
|
if (hasUVs) {
|
|
let uvs = threeJson.data.attributes.uv.array;
|
|
for (let i = 0; i < uvs.length; i += 2) {
|
|
let x = uvs[i];
|
|
let y = uvs[i + 1];
|
|
mesh.AddTextureUV (new OV.Coord2D (x, y));
|
|
}
|
|
}
|
|
let indices = threeJson.data.index.array;
|
|
for (let i = 0; i < indices.length; i += 3) {
|
|
let v0 = indices[i];
|
|
let v1 = indices[i + 1];
|
|
let v2 = indices[i + 2];
|
|
let triangle = new OV.Triangle (v0, v1, v2);
|
|
if (hasNormals) {
|
|
triangle.SetNormals (v0, v1, v2);
|
|
}
|
|
if (hasUVs) {
|
|
triangle.SetTextureUVs (v0, v1, v2);
|
|
}
|
|
if (materialIndex !== null) {
|
|
triangle.SetMaterial (materialIndex);
|
|
}
|
|
mesh.AddTriangle (triangle);
|
|
}
|
|
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.AddMesh (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 = new OV.Material ();
|
|
if (rhinoMaterial === null) {
|
|
material.diffuse.Set (255, 255, 255);
|
|
} else {
|
|
material.name = rhinoMaterial.name;
|
|
SetColor (material.ambient, rhinoMaterial.ambientColor);
|
|
SetColor (material.diffuse, rhinoMaterial.diffuseColor);
|
|
SetColor (material.specular, rhinoMaterial.specularColor);
|
|
material.opacity = 1.0 - rhinoMaterial.transparency;
|
|
OV.UpdateMaterialTransparency (material);
|
|
// material.shininess = rhinoMaterial.shine / 255.0;
|
|
if (IsBlack (material.diffuse) && !IsWhite (rhinoMaterial.reflectionColor)) {
|
|
SetColor (material.diffuse, rhinoMaterial.reflectionColor);
|
|
}
|
|
if (IsBlack (material.diffuse) && !IsWhite (rhinoMaterial.transparentColor)) {
|
|
SetColor (material.diffuse, rhinoMaterial.transparentColor);
|
|
}
|
|
}
|
|
for (let i = 0; i < model.MaterialCount (); i++) {
|
|
let current = model.GetMaterial (i);
|
|
if (current.name !== material.name) {
|
|
continue;
|
|
}
|
|
if (!OV.ColorIsEqual (current.ambient, material.ambient)) {
|
|
continue;
|
|
}
|
|
if (!OV.ColorIsEqual (current.diffuse, material.diffuse)) {
|
|
continue;
|
|
}
|
|
if (!OV.ColorIsEqual (current.specular, material.specular)) {
|
|
continue;
|
|
}
|
|
if (!OV.IsEqual (current.opacity, material.opacity)) {
|
|
continue;
|
|
}
|
|
if (current.transparent !== material.transparent) {
|
|
continue;
|
|
}
|
|
if (!OV.IsEqual (current.shininess, material.shininess)) {
|
|
continue;
|
|
}
|
|
return i;
|
|
}
|
|
return model.AddMaterial (material);
|
|
}
|
|
|
|
let rhinoMaterial = GetRhinoMaterial (this.rhino, rhinoObject, rhinoInstanceReferences);
|
|
return FindMatchingMaterial (this.model, rhinoMaterial);
|
|
}
|
|
};
|