PDF3D/PDF3D.Addin/IDTFBuilder.cs
2023-04-24 16:20:24 +08:00

255 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.DB;
using Duffer;
namespace PDF3D.Addin
{
internal class IDTFBuilder
{
private readonly Document document;
private IDTFScene _scene;
private Dictionary<string, int> _shaderIndex = new Dictionary<string, int>();
private Parent nullParent = new Duffer.Parent() { Name = "<NULL>", Transform = new Duffer.Transform4x4() };
private ShadingDescription defaultShadingDesc = new Duffer.ShadingDescription() { TextureCoordDimensionList = new List<int>(), ShaderID = 0 };
public IDTFBuilder(Autodesk.Revit.DB.Document document)
{
this.document = document;
this._scene = new IDTFScene();
// AddDefault();
}
private void AddDefault()
{
var mat = new Duffer.MaterialResource()
{
Name = "default",
AttributeDiffuseEnabled = true,
MaterialDiffuse = System.Drawing.Color.FromArgb(255, 125, 125, 125),
};
this._scene.MaterialResources.Add(mat.Name, mat);
this._scene.ShaderResources.Add(mat.Name, new ShaderResource() { /*AttributeAlphaTestEnabled = true,*/ ShaderMaterialName = mat.Name, Name = mat.Name });
_shaderIndex.Add(mat.Name, this._scene.ShaderResources.Count);
}
public bool InsertGroup(string name, string patrent = "")
{
if (this._scene.Groups.Any(x => x.Name == name))
{
return false;
}
else
{
var group = new Duffer.Group() { Name = name, Parents = new List<Duffer.Parent>() { _scene.Groups.Any(x => x.Name == patrent) ? new Parent(patrent) : nullParent } };
this._scene.Groups.Add(group);
return true;
}
}
public bool InsertMaterial(Material material)
{
if (material == null)
{
if (!this._scene.MaterialResources.ContainsKey("default"))
{
AddDefault();
}
return false;
}
else if (!this._scene.MaterialResources.ContainsKey(material.Name))
{
var mat = new Duffer.MaterialResource()
{
Name = material.Name,
MaterialDiffuse = System.Drawing.Color.FromArgb(255, material.Color.Red, material.Color.Green, material.Color.Blue),
MaterialOpacity = (100 - material.Transparency) / 100f
};
this._scene.MaterialResources.Add(mat.Name, mat);
this._scene.ShaderResources.Add(mat.Name, new ShaderResource() { /*AttributeAlphaTestEnabled = true,*/ ShaderMaterialName = mat.Name, Name = mat.Name });
_shaderIndex.Add(mat.Name, this._scene.ShaderResources.Count);
return true;
}
return false;
}
public bool InsertElement(Element element)
{
Duffer.Parent parent;
if (element is FamilyInstance fi)
{
this.InsertGroup(fi.Symbol.FamilyName, fi.Category.Name);
parent = new Duffer.Parent(fi.Symbol.FamilyName);
}
else
{
parent = new Duffer.Parent(element.Category.Name);
}
var option = new Options();
option.ComputeReferences = true;
option.DetailLevel = ViewDetailLevel.Fine;
option.IncludeNonVisibleObjects = false;
GeometryElement geoElement = element.get_Geometry(option);
var meshData = ConvertGeometryObject(geoElement);
if (meshData != null && meshData.ModelPositionList.Any())
{
var name = element.Name + " " + element.Id.ToString();
var model = new Duffer.Model
{
Name = name,
Parents = new List<Duffer.Parent>() { parent },
Visibility = ModelVisibility.BOTH
};
var modelRes = new Duffer.ModelResource(Duffer.ModelType.MESH) { Name = name };
modelRes.Mesh = meshData;
model.Resource = modelRes;
_scene.Models.Add(model);
_scene.ModelResources.Add(name, modelRes);
}
return false;
}
private MeshData ConvertGeometryObject(GeometryObject go)
{
if (go is GeometryElement ge)
{
MeshData meshData = new MeshData();
foreach (var item in ge)
{
var data = ConvertGeometryObject(item);
if (data != null)
{
CombineMeshdata(meshData, data);
}
}
return meshData;
}
if (go is GeometryInstance gi)
{
return ConvertGeometryObject(gi.GetInstanceGeometry());
}
if (go is Face face)
{
var faceMesh = face.Triangulate(0.4);
MeshData meshData = new MeshData();
meshData.ModelPositionList.AddRange(faceMesh.Vertices.Select(p => new Point3((float)p.X * 304.8f, (float)p.Y * 304.8f, (float)p.Z * 304.8f)));
for (int i = 0; i < faceMesh.NumTriangles; i++)
{
var tri = faceMesh.get_Triangle(i);
meshData.MeshFacePositionList.Add(new Int3((int)tri.get_Index(0), (int)tri.get_Index(1), (int)tri.get_Index(2)));
}
var material = face?.MaterialElementId.IntegerValue > 0
? (document.GetElement(face?.MaterialElementId) as Autodesk.Revit.DB.Material) : null;
this.InsertMaterial(material);
var shaderDesc = material == null ? new ShadingDescription(_shaderIndex["default"]) : new ShadingDescription(_shaderIndex[material.Name]);
// System.Drawing.Color color = material == null ? System.Drawing.Color.FromArgb(255, 125, 125, 125)
// : System.Drawing.Color.FromArgb((int)((100 - material.Transparency) / 100f * 255), material.Color.Red, material.Color.Green, material.Color.Blue);
// meshData.ModelDiffuseColorList.Add(color);
meshData.ShadingDescriptionList.Add(shaderDesc);
for (int i = 0; i < meshData.MeshFacePositionList.Count; i++)
{
// meshData.MeshFaceDiffuseColorList.Add(new Int3(0, 0, 0));
meshData.MeshFaceShadingList.Add(0);
}
return meshData;
}
if (go is Mesh mesh)
{
MeshData meshData = new MeshData();
meshData.ModelPositionList.AddRange(mesh.Vertices.Select(p => new Point3((float)p.X * 304.8f, (float)p.Y * 304.8f, (float)p.Z * 304.8f)));
for (int i = 0; i < mesh.NumTriangles; i++)
{
var tri = mesh.get_Triangle(i);
meshData.MeshFacePositionList.Add(new Int3((int)tri.get_Index(0), (int)tri.get_Index(1), (int)tri.get_Index(2)));
}
var material = mesh?.MaterialElementId.IntegerValue > 0
? (document.GetElement(mesh?.MaterialElementId) as Autodesk.Revit.DB.Material) : null;
this.InsertMaterial(material);
var shaderDesc = material == null ? new ShadingDescription(_shaderIndex["default"]) : new ShadingDescription(_shaderIndex[material.Name]);
//System.Drawing.Color color = material == null ? System.Drawing.Color.FromArgb(255, 125, 125, 125)
// : System.Drawing.Color.FromArgb((int)((100 - material.Transparency) / 100f * 255), material.Color.Red, material.Color.Green, material.Color.Blue);
//meshData.ModelDiffuseColorList.Add(color);
meshData.ShadingDescriptionList.Add(shaderDesc);
for (int i = 0; i < meshData.MeshFacePositionList.Count; i++)
{
// meshData.MeshFaceDiffuseColorList.Add(new Int3(0, 0, 0));
meshData.MeshFaceShadingList.Add(0);
}
return meshData;
}
if (go is Solid solid)
{
var meshData = new MeshData();
if (solid.Volume != 0)
{
foreach (Face item in solid.Faces)
{
var data = ConvertGeometryObject(item);
if (data != null)
{
CombineMeshdata(meshData, data);
}
}
}
return meshData;
}
return null;
}
private void CombineMeshdata(MeshData data1, MeshData data2)
{
var oldCount = data1.ModelPositionList.Count;
data1.ModelPositionList.AddRange(data2.ModelPositionList);
data1.MeshFacePositionList.AddRange(data2.MeshFacePositionList.Select(x => new Int3(x.IntArray[0] + oldCount, x.IntArray[1] + oldCount, x.IntArray[2] + oldCount)));
for (int i = 0; i < data2.MeshFaceDiffuseColorList.Count; i++)
{
int index = data2.MeshFaceDiffuseColorList[i].IntArray.ElementAt(0);
var color = data2.ModelDiffuseColorList[index];
int colorIndex = data1.ModelDiffuseColorList.IndexOf(color);
if (colorIndex != -1)
{
data1.MeshFaceDiffuseColorList.Add(new Int3(colorIndex, colorIndex, colorIndex));
}
else
{
data1.ModelDiffuseColorList.Add(color);
data1.MeshFaceDiffuseColorList.Add(new Int3(data1.ModelDiffuseColorList.Count - 1, data1.ModelDiffuseColorList.Count - 1, data1.ModelDiffuseColorList.Count - 1));
}
}
for (int i = 0; i < data2.MeshFaceShadingList.Count; i++)
{
var index = data2.MeshFaceShadingList[i];
var shader = data2.ShadingDescriptionList[index];
if (data1.ShadingDescriptionList.Any(x => x.ShaderID == shader.ShaderID))
{
int shaderIndex = data1.ShadingDescriptionList.IndexOf(data1.ShadingDescriptionList.FirstOrDefault(x => x.ShaderID == shader.ShaderID));
data1.MeshFaceShadingList.Add(shaderIndex);
}
else
{
data1.ShadingDescriptionList.Add(shader);
data1.MeshFaceShadingList.Add(data1.ShadingDescriptionList.Count - 1);
}
}
}
public void Export(string path)
{
_scene.Export(path);
}
}
}