Mesh共用、顶点合并

This commit is contained in:
zhangXQ 2021-02-28 11:38:29 +08:00
parent e5e28afc3f
commit 341b9efe3c
9 changed files with 229 additions and 159 deletions

View File

@ -11,27 +11,33 @@ namespace NwGeoExporter
{ {
public class CustomExporter : InwSimplePrimitivesCB public class CustomExporter : InwSimplePrimitivesCB
{ {
private TransformM transform3D; //private TransformM transform3D;
public CustomExporter() public CustomExporter()
{ {
Triangles = new List<Triangle>(); Triangles = new List<Triangle>();
} }
public CustomExporter(TransformM transform3D):this() //public CustomExporter(TransformM transform3D):this()
{ //{
this.transform3D = transform3D; // this.transform3D = transform3D;
} //}
public List<Triangle> Triangles { get; set; } public List<Triangle> Triangles { get; set; }
public void Triangle(InwSimpleVertex v1, InwSimpleVertex v2, InwSimpleVertex v3) public void Triangle(InwSimpleVertex v1, InwSimpleVertex v2, InwSimpleVertex v3)
{ {
//var vertices = new PointM[]
// {
// transform3D.OfPoint(new PointM(v1)),
// transform3D.OfPoint(new PointM(v2)),
// transform3D.OfPoint(new PointM(v3)),
// };
var vertices = new PointM[] var vertices = new PointM[]
{ {
transform3D.OfPoint(new PointM(v1)), new PointM(v1),
transform3D.OfPoint(new PointM(v2)), new PointM(v2),
transform3D.OfPoint(new PointM(v3)), new PointM(v3),
}; };
var normals = new VectorM[] var normals = new VectorM[]
{ {

View File

@ -22,24 +22,8 @@ namespace NwGeoExporter.Models
[JsonIgnore] [JsonIgnore]
public TransformM Transform { get; set; } public TransformM Transform { get; set; }
///// <summary>
///// 转换-序列化(列主序)
///// </summary>
//public double[] transform
//{
// get
// {
// return new double[]
// {
// Transform.BasicX.X,Transform.BasicX.Y,Transform.BasicX.Z,0
// ,Transform.BasicY.X,Transform.BasicY.Y,Transform.BasicY.Z,0
// ,Transform.BasicZ.X,Transform.BasicZ.Y,Transform.BasicZ.Z,0
// ,Transform.Origin.X,Transform.Origin.Y,Transform.Origin.Z,1
// };
// }
//}
/// <summary> /// <summary>
/// 转换-序列化(主序) /// 转换-序列化(列主序)
/// </summary> /// </summary>
public double[] transform public double[] transform
{ {
@ -50,10 +34,11 @@ namespace NwGeoExporter.Models
Transform.BasicX.X,Transform.BasicX.Y,Transform.BasicX.Z,0 Transform.BasicX.X,Transform.BasicX.Y,Transform.BasicX.Z,0
,Transform.BasicY.X,Transform.BasicY.Y,Transform.BasicY.Z,0 ,Transform.BasicY.X,Transform.BasicY.Y,Transform.BasicY.Z,0
,Transform.BasicZ.X,Transform.BasicZ.Y,Transform.BasicZ.Z,0 ,Transform.BasicZ.X,Transform.BasicZ.Y,Transform.BasicZ.Z,0
,Transform.Origin.X,Transform.Origin.Y,Transform.Origin.Z,1 ,Transform.Origin.X.Feet2Mm(),Transform.Origin.Y.Feet2Mm(),Transform.Origin.Z.Feet2Mm(),1
}; };
} }
} }
/// <summary> /// <summary>
/// 是否可见 /// 是否可见
/// </summary> /// </summary>

View File

@ -15,7 +15,7 @@ namespace NwGeoExporter.Models
/// 顶点数组-序列化数据 /// 顶点数组-序列化数据
/// </summary> /// </summary>
public double[] vertices { get => VerticeList.SelectMany(x => new List<double> { x.X.Feet2Mm(), x.Y.Feet2Mm(), x.Z.Feet2Mm() }).ToArray(); } public double[] vertices { get => VerticeList.SelectMany(x => new List<double> { x.X.Feet2Mm(), x.Y.Feet2Mm(), x.Z.Feet2Mm() }).ToArray(); }
//public double[] vertices { get => VerticeList.SelectMany(x => new List<double> { x.X, x.Y, x.Z }).ToArray(); }
/// <summary> /// <summary>
/// 顶点索引-序列化数据 /// 顶点索引-序列化数据
/// </summary> /// </summary>
@ -71,35 +71,63 @@ namespace NwGeoExporter.Models
{ {
for (int i = 0; i < triangle.Vertices.Length; i++) for (int i = 0; i < triangle.Vertices.Length; i++)
{ {
// bool isHandle = false; bool isHandle = false;
// for (int j = 0; j < VerticeList.Count; j++) //相同的顶点位置的索引
// { List<int> indexList = VerticeList.FindIndexs(x => x == triangle.Vertices[i]);
// if (VerticeList[j] == triangle.vertices[i]) //当前三角面片顶点法向
// { VectorM currentVector = triangle.Normals[i];
// //拿到索引集合中与当前顶点值一样的索引 //最后一次合并的索引
// List<int> indexList = IndiceList.FindIndexs(x => x == j); int lastMergeIndex = 0;
while (indexList.Count != 0)
{
//判断索引内是否需要合并的顶点
var index = indexList.FindIndex(x => NormalList[x].AngelTo(currentVector).ToAngle() - 90 > 0.1);
if (index == -1)
{
break;
}
else if (!isHandle)//第一次
{
NormalList[indexList[index]] = (currentVector + NormalList[indexList[index]]).Normalize();
currentVector = NormalList[indexList[index]];
lastMergeIndex = indexList[index];
indexList.RemoveAt(index);
isHandle = true;
}
else//原来顶点位置一致的与合并后的顶点进行比较
{
int removeIndex = Math.Max(lastMergeIndex, indexList[index]);
lastMergeIndex = Math.Min(lastMergeIndex, indexList[index]);
// //TODO考虑多个的情况 //重置索引
// //第几个需要跟当前顶点法向进行平均 for (int k = 0; k < IndiceList.Count; k++)
// int index = indexList.FindIndex(x => NormalList[x] {
// .AngelTo(triangle.normals[i]).ToAngle() - 90 > 0.1); if (IndiceList[k] > removeIndex)
// //有遇到顶点法线平均 {
// if (index != -1) IndiceList[k]--;
// { }
// NormalList[j] = (triangle.normals[i] + NormalList[j]).Normalize(); else if (IndiceList[k] == removeIndex)
// isHandle = true; {
// break; IndiceList[k] = lastMergeIndex;
// } }
// } }
// }
// if (!isHandle) //删除不需要的顶点和法向
// { NormalList.RemoveAt(removeIndex);
VerticeList.RemoveAt(removeIndex);
}
}
if (!isHandle)
{
//添加顶点以及顶点法向以及对应的索引 //添加顶点以及顶点法向以及对应的索引
VerticeList.Add(triangle.Vertices[i]); VerticeList.Add(triangle.Vertices[i]);
NormalList.Add(triangle.Normals[i]); NormalList.Add(triangle.Normals[i]);
IndiceList.Add(VerticeList.Count - 1); IndiceList.Add(VerticeList.Count - 1);
}else
{
IndiceList.Add(lastMergeIndex);
}
} }
//}
} }
public void AddTriangles(IEnumerable<Triangle> triangles) public void AddTriangles(IEnumerable<Triangle> triangles)

View File

@ -42,7 +42,7 @@ namespace NwGeoExporter.Models
{ {
if (obj is PointM pm) if (obj is PointM pm)
{ {
if (pm.X.Round(6) == X.Round(6) && pm.Y.Round(6) == Y.Round(6) && pm.Z.Round(6) == Z.Round(6)) if (pm.X.Round(4) == X.Round(4) && pm.Y.Round(4) == Y.Round(4) && pm.Z.Round(4) == Z.Round(4))
return true; return true;
} }
return false; return false;

View File

@ -27,7 +27,7 @@ namespace NwGeoExporter.Models
Origin = new PointM(), Origin = new PointM(),
}; };
} }
private InwLTransform3f3 inwTransform; //private InwLTransform3f3 inwTransform;
private TransformM() private TransformM()
{ {
@ -44,31 +44,31 @@ namespace NwGeoExporter.Models
BasicY = new VectorM(matrixElements[4], matrixElements[5], matrixElements[6]); BasicY = new VectorM(matrixElements[4], matrixElements[5], matrixElements[6]);
BasicZ = new VectorM(matrixElements[8], matrixElements[9], matrixElements[10]); BasicZ = new VectorM(matrixElements[8], matrixElements[9], matrixElements[10]);
Origin = new PointM(matrixElements[12], matrixElements[13], matrixElements[14]); Origin = new PointM(matrixElements[12], matrixElements[13], matrixElements[14]);
this.inwTransform = inwTransform; //this.inwTransform = inwTransform;
}
public PointM OfPoint(PointM point)
{
double[] matrixElements = ((Array)(object)inwTransform.Matrix).ToArray<double>();
double x = point.X;
double y = point.Y;
double z = point.Z;
double w = matrixElements[3] * x + matrixElements[7] * y + matrixElements[11] * z + matrixElements[15];
return new PointM(
(matrixElements[0] * x + matrixElements[4] * y + matrixElements[8] * z + matrixElements[12]) / w,
(matrixElements[1] * x + matrixElements[5] * y + matrixElements[9] * z + matrixElements[13]) / w,
(matrixElements[2] * x + matrixElements[6] * y + matrixElements[10] * z + matrixElements[14]) / w);
} }
//public PointM OfPoint(PointM point) //public PointM OfPoint(PointM point)
//{ //{
// double[] matrixElements = ((Array)(object)inwTransform.Matrix).ToArray<double>();
// double x = point.X; // double x = point.X;
// double y = point.Y; // double y = point.Y;
// double z = point.Z; // double z = point.Z;
// return // double w = matrixElements[3] * x + matrixElements[7] * y + matrixElements[11] * z + matrixElements[15];
// new PointM( // return new PointM(
// BasicX.X * x + BasicY.X * y + BasicZ.X * z + Origin.X, //(matrixElements[0] * x + matrixElements[4] * y + matrixElements[8] * z + matrixElements[12]) / w,
// BasicX.Y * x + BasicY.Y * y + BasicZ.Y * z + Origin.Y, //(matrixElements[1] * x + matrixElements[5] * y + matrixElements[9] * z + matrixElements[13]) / w,
// BasicX.Z * x + BasicY.Z * y + BasicZ.Z * z + Origin.Z //(matrixElements[2] * x + matrixElements[6] * y + matrixElements[10] * z + matrixElements[14]) / w);
// );
//} //}
public PointM OfPoint(PointM point)
{
double x = point.X;
double y = point.Y;
double z = point.Z;
return
new PointM(
BasicX.X * x + BasicY.X * y + BasicZ.X * z + Origin.X,
BasicX.Y * x + BasicY.Y * y + BasicZ.Y * z + Origin.Y,
BasicX.Z * x + BasicY.Z * y + BasicZ.Z * z + Origin.Z
);
}
} }
} }

View File

@ -1,4 +1,5 @@
using System; using Autodesk.Navisworks.Api;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -41,7 +42,20 @@ namespace NwGeoExporter.NwEx
} }
return -1; return -1;
} }
/// <summary>
/// 转ModelItemCollection
/// </summary>
/// <param name="items"></param>
/// <returns></returns>
public static ModelItemCollection ToCollection(this IEnumerable<ModelItem> items)
{
ModelItemCollection collection = new ModelItemCollection();
foreach (var it in items)
{
collection.Add(it);
}
return collection;
}
/// <summary> /// <summary>
/// 找到所有的索引 /// 找到所有的索引
/// </summary> /// </summary>
@ -61,7 +75,7 @@ namespace NwGeoExporter.NwEx
indexList.Add(i); indexList.Add(i);
} }
} }
return indexList.Count == 0 ? null : indexList; return indexList.Count == 0 ? new List<int>() : indexList;
} }
} }
} }

View File

@ -42,6 +42,11 @@ namespace NwGeoExporter
//获取项目树中的子项 //获取项目树中的子项
var modelItemColl = ModelItemUtils.GetModelItems(doc); var modelItemColl = ModelItemUtils.GetModelItems(doc);
//分组(子项中有相同几何数据的分为一组)
var itemGroup = modelItemColl.GroupBy(x => x, new BaseComparer<ModelItem>((x, y) => x.IsSameInstance(y))).Select(x => x.ToList()).ToList();
//取其中一个
modelItemColl = itemGroup.Select(x => x.First()).ToCollection();
//转换成选择集 //转换成选择集
COMApi.InwOpSelection selItemColl = COMApi.InwOpSelection selItemColl =
ComBridge.ToInwOpSelection(modelItemColl); ComBridge.ToInwOpSelection(modelItemColl);
@ -51,29 +56,20 @@ namespace NwGeoExporter
{ {
//是否是可载入族 //是否是可载入族
bool isInstance = ModelItemUtils.IsRevitInstance(modelItemColl[index].Parent.Parent); bool isInstance = ModelItemUtils.IsRevitInstance(modelItemColl[index].Parent.Parent);
Mesh mesh = null;
#region Mesh材质 int instanceIndex = 0;
//材质属性 foreach (COMApi.InwOaFragment3 frag in path.Fragments())
var material = GetMaterial(modelItemColl[index].Parent);
//查找材质索引
int matIndex = materialList.FindIndex(x => x.Equals(material));
if (matIndex == -1)
{ {
materialList.Add(material);
matIndex = materialList.Count - 1;
}
#endregion
#region Revit元素属性 #region Revit元素属性
Dictionary<string, string> elemPropertyDict = new Dictionary<string, string>(); Dictionary<string, string> elemPropertyDict = new Dictionary<string, string>();
DataPropertyCollection elemPropertyColl = null; DataPropertyCollection elemPropertyColl = null;
if (isInstance) if (isInstance)
{ {
elemPropertyColl = GetDataPropertys(modelItemColl[index].Parent.Parent, PropertyCategoryName.LcRevitData_Element); elemPropertyColl = GetDataPropertys(itemGroup[index][instanceIndex].Parent.Parent, PropertyCategoryName.LcRevitData_Element);
} }
else else
{ {
elemPropertyColl = GetDataPropertys(modelItemColl[index].Parent, PropertyCategoryName.LcRevitData_Element); elemPropertyColl = GetDataPropertys(itemGroup[index][instanceIndex].Parent, PropertyCategoryName.LcRevitData_Element);
} }
//二级是系统族获取元素属性的方法 //二级是系统族获取元素属性的方法
foreach (var elemProperty in elemPropertyColl) foreach (var elemProperty in elemPropertyColl)
@ -103,36 +99,48 @@ namespace NwGeoExporter
} }
#endregion #endregion
#region Mesh
Mesh mesh = new Mesh(matIndex);
TransformM transform3D = null;
foreach (COMApi.InwOaFragment3 frag in path.Fragments())
{
//if (transform3D == null)
//{
InwLTransform3f3 localToWorld = (InwLTransform3f3)frag.GetLocalToWorldMatrix(); InwLTransform3f3 localToWorld = (InwLTransform3f3)frag.GetLocalToWorldMatrix();
transform3D = new TransformM(localToWorld); var transform3D = new TransformM(localToWorld);
//} if (mesh == null)
CustomExporter customExporter = new CustomExporter(transform3D); {
#region Mesh材质
//材质属性
var material = GetMaterial(modelItemColl[index].Parent);
//查找材质索引
int matIndex = materialList.FindIndex(x => x.Equals(material));
if (matIndex == -1)
{
materialList.Add(material);
matIndex = materialList.Count - 1;
}
#endregion
mesh = new Mesh(matIndex);
CustomExporter customExporter = new CustomExporter();
// generate the primitives // generate the primitives
frag.GenerateSimplePrimitives(COMApi.nwEVertexProperty.eNORMAL, customExporter); frag.GenerateSimplePrimitives(COMApi.nwEVertexProperty.eNORMAL, customExporter);
mesh.AddTriangles(customExporter.Triangles); mesh.AddTriangles(customExporter.Triangles);
}
meshList.Add(mesh); meshList.Add(mesh);
#endregion }
#region Instance对象 #region Instance对象
Instance currentInstance = new Instance() Instance currentInstance = new Instance()
{ {
id = elemID, id = elemID,
mesh = meshList.Count - 1, mesh = meshList.Count - 1,
Transform = TransformM.Identify, Transform = transform3D,
visible = 1.0, visible = 1.0,
info = elemPropertyDict, info = elemPropertyDict,
}; };
instanceList.Add(currentInstance);
index++;
#endregion #endregion
instanceList.Add(currentInstance);
instanceIndex++;
}
index++;
} }
NwModel model = new NwModel(instanceList, meshList, materialList); NwModel model = new NwModel(instanceList, meshList, materialList);

View File

@ -71,6 +71,7 @@
<Compile Include="NwExporterPlugin.cs" /> <Compile Include="NwExporterPlugin.cs" />
<Compile Include="NwEx\IEnumerableEx.cs" /> <Compile Include="NwEx\IEnumerableEx.cs" />
<Compile Include="NwEx\MathEx.cs" /> <Compile Include="NwEx\MathEx.cs" />
<Compile Include="NwUtils\BaseComparer.cs" />
<Compile Include="NwUtils\JsonUtils.cs" /> <Compile Include="NwUtils\JsonUtils.cs" />
<Compile Include="NwUtils\ModelUtils.cs" /> <Compile Include="NwUtils\ModelUtils.cs" />
<Compile Include="NwUtils\PropertyUtils.cs" /> <Compile Include="NwUtils\PropertyUtils.cs" />

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NwGeoExporter.NwUtils
{
public class BaseComparer<T> : IEqualityComparer<T>
{
public BaseComparer(Func<T,T,bool> func)
{
Func = func;
}
private Func<T, T, bool> Func { get; }
public bool Equals(T x, T y)
{
return (bool)Func?.Invoke(x, y);
}
public int GetHashCode(T obj)
{
return 0;
}
}
}