public XbimGeometryData TransformBy(XbimMatrix3D matrix) { XbimMatrix3D t = XbimMatrix3D.FromArray(DataArray2); t = XbimMatrix3D.Multiply(t, matrix); return(new XbimGeometryData(GeometryLabel, IfcProductLabel, GeometryType, IfcTypeId, ShapeData, t.ToArray(), GeometryHash, StyleLabel, Counter)); }
/// <summary> /// Builds a windows Matrix3D from an ObjectPlacement /// Conversion fo c++ function CartesianTransform::ConvertMatrix3D from CartesianTransform.cpp /// </summary> /// <param name="objPlacement">IfcObjectPlacement object</param> /// <returns>Matrix3D</returns> protected XbimMatrix3D ConvertMatrix3D(IfcObjectPlacement objPlacement) { if (objPlacement is IfcLocalPlacement) { IfcLocalPlacement locPlacement = (IfcLocalPlacement)objPlacement; if (locPlacement.RelativePlacement is IfcAxis2Placement3D) { IfcAxis2Placement3D axis3D = (IfcAxis2Placement3D)locPlacement.RelativePlacement; XbimVector3D ucsXAxis = new XbimVector3D(axis3D.RefDirection.DirectionRatios[0], axis3D.RefDirection.DirectionRatios[1], axis3D.RefDirection.DirectionRatios[2]); XbimVector3D ucsZAxis = new XbimVector3D(axis3D.Axis.DirectionRatios[0], axis3D.Axis.DirectionRatios[1], axis3D.Axis.DirectionRatios[2]); ucsXAxis = ucsXAxis.Normalized(); ucsZAxis = ucsZAxis.Normalized(); XbimVector3D ucsYAxis = XbimVector3D.CrossProduct(ucsZAxis, ucsXAxis); ucsYAxis = ucsYAxis.Normalized(); XbimPoint3D ucsCentre = axis3D.Location.XbimPoint3D(); XbimMatrix3D ucsTowcs = new XbimMatrix3D(ucsXAxis.X, ucsXAxis.Y, ucsXAxis.Z, 0, ucsYAxis.X, ucsYAxis.Y, ucsYAxis.Z, 0, ucsZAxis.X, ucsZAxis.Y, ucsZAxis.Z, 0, ucsCentre.X, ucsCentre.Y, ucsCentre.Z, 1); if (locPlacement.PlacementRelTo != null) { return(XbimMatrix3D.Multiply(ucsTowcs, ConvertMatrix3D(locPlacement.PlacementRelTo))); } return(ucsTowcs); } throw new NotImplementedException("Support for Placements other than 3D not implemented"); } throw new NotImplementedException("Support for Placements other than Local not implemented"); }
public static void AddElements(this MeshGeometry3D m, IPersistIfcEntity item, XbimMatrix3D wcsTransform) { var fromModel = item.ModelOf as XbimModel; if (fromModel == null || !(item is IfcProduct)) { return; } switch (fromModel.GeometrySupportLevel) { case 2: var context = new Xbim3DModelContext(fromModel); var productShape = context.ShapeInstancesOf((IfcProduct)item) .Where(s => s.RepresentationType != XbimGeometryRepresentationType.OpeningsAndAdditionsExcluded) .ToList(); if (!productShape.Any() && item is IfcFeatureElement) { productShape = context.ShapeInstancesOf((IfcProduct)item) .Where( s => s.RepresentationType == XbimGeometryRepresentationType.OpeningsAndAdditionsExcluded) .ToList(); } if (!productShape.Any()) { return; } foreach (var shapeInstance in productShape) { IXbimShapeGeometryData shapeGeom = context.ShapeGeometry(shapeInstance.ShapeGeometryLabel); switch ((XbimGeometryType)shapeGeom.Format) { case XbimGeometryType.PolyhedronBinary: m.Read(shapeGeom.ShapeData, XbimMatrix3D.Multiply(shapeInstance.Transformation, wcsTransform)); break; case XbimGeometryType.Polyhedron: m.Read(((XbimShapeGeometry)shapeGeom).ShapeData, XbimMatrix3D.Multiply(shapeInstance.Transformation, wcsTransform)); break; } } break; case 1: var xm3d = new XbimMeshGeometry3D(); var geomDataSet = fromModel.GetGeometryData(item.EntityLabel, XbimGeometryType.TriangulatedMesh); foreach (var geomData in geomDataSet) { var gd = geomData.TransformBy(wcsTransform); xm3d.Add(gd); } m.Add(xm3d); break; } }
/// <summary> /// If translation is defined, returns matrix translated by the vector /// </summary> /// <param name="matrix">Input matrix</param> /// <param name="translation">Translation</param> /// <returns>Translated matrix</returns> private static XbimMatrix3D Translate(XbimMatrix3D matrix, IVector3D translation) { if (translation == null) { return(matrix); } var translationMatrix = XbimMatrix3D.CreateTranslation(translation.X, translation.Y, translation.Z); return(XbimMatrix3D.Multiply(matrix, translationMatrix)); }
public void GetGeometryFromXbimModel_IFC4(MeshGeometry3D m, IPersistEntity item, XbimMatrix3D wcsTransform) { if (item.Model == null || !(item is Xbim.Ifc4.Kernel.IfcProduct)) { return; } var context = new Xbim3DModelContext(item.Model); var productShape = context.ShapeInstancesOf((Xbim.Ifc4.Interfaces.IIfcProduct)item) .Where(s => s.RepresentationType != XbimGeometryRepresentationType.OpeningsAndAdditionsExcluded) .ToList(); if (!productShape.Any() && item is Xbim.Ifc4.Interfaces.IIfcFeatureElement) { productShape = context.ShapeInstancesOf((Xbim.Ifc4.Interfaces.IIfcProduct)item) .Where( s => s.RepresentationType == XbimGeometryRepresentationType.OpeningsAndAdditionsExcluded) .ToList(); } if (!productShape.Any()) { return; } foreach (var shapeInstance in productShape) { IXbimShapeGeometryData shapeGeom = context.ShapeGeometry(shapeInstance.ShapeGeometryLabel); switch ((XbimGeometryType)shapeGeom.Format) { case XbimGeometryType.PolyhedronBinary: m.Read(shapeGeom.ShapeData, XbimMatrix3D.Multiply(shapeInstance.Transformation, wcsTransform)); break; case XbimGeometryType.Polyhedron: m.Read(((XbimShapeGeometry)shapeGeom).ShapeData, XbimMatrix3D.Multiply(shapeInstance.Transformation, wcsTransform)); break; } } }
public XbimScene <WpfMeshGeometry3D, WpfMaterial> BuildScene(XbimModel model, Xbim3DModelContext context, List <Type> exclude = null) { var tmpOpaquesGroup = new Model3DGroup(); var retScene = new XbimScene <WpfMeshGeometry3D, WpfMaterial>(model); var red = PrepareMesh(new XbimColour("Red", 1.0, 0.0, 0.0, 0.5)); var green = PrepareMesh(new XbimColour("Green", 0.0, 1.0, 0.0, 0.5)); red.WpfModel.SetValue(FrameworkElement.TagProperty, red); green.WpfModel.SetValue(FrameworkElement.TagProperty, green); red.BeginUpdate(); green.BeginUpdate(); tmpOpaquesGroup.Children.Add(red); tmpOpaquesGroup.Children.Add(green); var i = 0; foreach (var shapeInstance in context.ShapeInstances() .Where(s => s.RepresentationType == XbimGeometryRepresentationType.OpeningsAndAdditionsIncluded && !typeof(IfcFeatureElement).IsAssignableFrom(IfcMetaData.GetType(s.IfcTypeId)) /*&& * !typeof(IfcSpace).IsAssignableFrom(IfcMetaData.GetType(s.IfcTypeId))*/)) { IXbimShapeGeometryData shapeGeom = context.ShapeGeometry(shapeInstance.ShapeGeometryLabel); WpfMeshGeometry3D targetMergeMesh; switch (i++ % 2) { case 0: targetMergeMesh = red; break; default: targetMergeMesh = green; break; } switch ((XbimGeometryType)shapeGeom.Format) { case XbimGeometryType.Polyhedron: var shapePoly = (XbimShapeGeometry)shapeGeom; targetMergeMesh.Add( shapePoly.ShapeData, shapeInstance.IfcTypeId, shapeInstance.IfcProductLabel, shapeInstance.InstanceLabel, XbimMatrix3D.Multiply(shapeInstance.Transformation, Control.ModelPositions[model].Transfrom), model.UserDefinedId); break; case XbimGeometryType.PolyhedronBinary: targetMergeMesh.Add( shapeGeom.ShapeData, shapeInstance.IfcTypeId, shapeInstance.IfcProductLabel, shapeInstance.InstanceLabel, XbimMatrix3D.Multiply(shapeInstance.Transformation, Control.ModelPositions[model].Transfrom), model.UserDefinedId ); break; default: throw new ArgumentOutOfRangeException(); } } red.EndUpdate(); green.EndUpdate(); var mv = new ModelVisual3D { Content = tmpOpaquesGroup }; Control.OpaquesVisual3D.Children.Add(mv); // Control.ModelBounds = mv.Content.Bounds.ToXbimRect3D(); return(retScene); }
/// <summary> /// This version uses the new Geometry representation /// </summary> /// <param name="model"></param> /// <param name="modelTransform">The transform to place the models geometry in the right place</param> /// <param name="opaqueShapes"></param> /// <param name="transparentShapes"></param> /// <param name="exclude">List of type to exclude, by default excplict openings and spaces are excluded if exclude = null</param> /// <returns></returns> public XbimScene <WpfMeshGeometry3D, WpfMaterial> BuildScene(IModel model, XbimMatrix3D modelTransform, ModelVisual3D opaqueShapes, ModelVisual3D transparentShapes, List <Type> exclude = null) { var excludedTypes = model.DefaultExclusions(exclude); var scene = new XbimScene <WpfMeshGeometry3D, WpfMaterial>(model); var timer = new Stopwatch(); timer.Start(); using (var geomStore = model.GeometryStore) { using (var geomReader = geomStore.BeginRead()) { var materialsByStyleId = new Dictionary <int, WpfMaterial>(); var meshesByStyleId = new Dictionary <int, WpfMeshGeometry3D>(); var tmpOpaquesGroup = new Model3DGroup(); var tmpTransparentsGroup = new Model3DGroup(); //get a list of all the unique style ids then build their style and mesh var sstyleIds = geomReader.StyleIds; foreach (var styleId in sstyleIds) { var wpfMaterial = GetWpfMaterial(model, styleId); materialsByStyleId.Add(styleId, wpfMaterial); var mg = GetNewStyleMesh(wpfMaterial, tmpTransparentsGroup, tmpOpaquesGroup); meshesByStyleId.Add(styleId, mg); } var shapeInstances = GetShapeInstancesToRender(geomReader, excludedTypes); var tot = 1; if (ProgressChanged != null) { // only enumerate if there's a need for progress update tot = shapeInstances.Count(); } var prog = 0; var lastProgress = 0; // !typeof (IfcFeatureElement).IsAssignableFrom(IfcMetaData.GetType(s.IfcTypeId)) /*&& // !typeof(IfcSpace).IsAssignableFrom(IfcMetaData.GetType(s.IfcTypeId))*/); foreach (var shapeInstance in shapeInstances) { // logging var currentProgress = 100 * prog++ / tot; if (currentProgress != lastProgress && ProgressChanged != null) { ProgressChanged(this, new ProgressChangedEventArgs(currentProgress, "Creating visuals")); lastProgress = currentProgress; } // work out style var styleId = shapeInstance.StyleLabel > 0 ? shapeInstance.StyleLabel : shapeInstance.IfcTypeId * -1; if (!materialsByStyleId.ContainsKey(styleId)) { // if the style is not available we build one by ExpressType var material2 = GetWpfMaterialByType(model, shapeInstance.IfcTypeId); materialsByStyleId.Add(styleId, material2); var mg = GetNewStyleMesh(material2, tmpTransparentsGroup, tmpOpaquesGroup); meshesByStyleId.Add(styleId, mg); } var boxRep = GetSlicedBoxRepresentation(shapeInstance.BoundingBox); var targetMergeMeshByStyle = meshesByStyleId[styleId]; var transform = XbimMatrix3D.Multiply(shapeInstance.Transformation, modelTransform); targetMergeMeshByStyle.Add( boxRep, shapeInstance.IfcTypeId, shapeInstance.IfcProductLabel, shapeInstance.InstanceLabel, transform, (short)model.UserDefinedId); } foreach (var wpfMeshGeometry3D in meshesByStyleId.Values) { wpfMeshGeometry3D.EndUpdate(); } if (tmpOpaquesGroup.Children.Any()) { var mv = new ModelVisual3D { Content = tmpOpaquesGroup }; opaqueShapes.Children.Add(mv); } if (tmpTransparentsGroup.Children.Any()) { var mv = new ModelVisual3D { Content = tmpTransparentsGroup }; transparentShapes.Children.Add(mv); } } } Logger.LogDebug("Time to load visual components: {0:F3} seconds", timer.Elapsed.TotalSeconds); ProgressChanged?.Invoke(this, new ProgressChangedEventArgs(0, "Ready")); return(scene); }
/// <summary> /// This version uses the new Geometry representation /// </summary> /// <param name="model"></param> /// <param name="modelTransform">The transform to place the models geometry in the right place</param> /// <param name="opaqueShapes"></param> /// <param name="transparentShapes"></param> /// <param name="exclude">List of type to exclude, by default excplict openings and spaces are excluded if exclude = null</param> /// <returns></returns> public XbimScene <WpfMeshGeometry3D, WpfMaterial> BuildScene(IModel model, XbimMatrix3D modelTransform, ModelVisual3D opaqueShapes, ModelVisual3D transparentShapes, List <Type> exclude = null) { var excludedTypes = model.DefaultExclusions(exclude); var scene = new XbimScene <WpfMeshGeometry3D, WpfMaterial>(model); var timer = new Stopwatch(); timer.Start(); using (var geomStore = model.GeometryStore) { using (var geomReader = geomStore.BeginRead()) { var materialsByStyleId = new Dictionary <int, WpfMaterial>(); var repeatedShapeGeometries = new Dictionary <int, MeshGeometry3D>(); var meshesByStyleId = new Dictionary <int, WpfMeshGeometry3D>(); var tmpOpaquesGroup = new Model3DGroup(); var tmpTransparentsGroup = new Model3DGroup(); //get a list of all the unique style ids then build their style and mesh var sstyleIds = geomReader.StyleIds; foreach (var styleId in sstyleIds) { var wpfMaterial = GetWpfMaterial(model, styleId); materialsByStyleId.Add(styleId, wpfMaterial); var mg = GetNewStyleMesh(wpfMaterial, tmpTransparentsGroup, tmpOpaquesGroup); meshesByStyleId.Add(styleId, mg); } var shapeInstances = geomReader.ShapeInstances .Where(s => s.RepresentationType == XbimGeometryRepresentationType.OpeningsAndAdditionsIncluded && !excludedTypes.Contains(s.IfcTypeId)); var tot = shapeInstances.Count(); var prog = 0; var lastProgress = 0; // !typeof (IfcFeatureElement).IsAssignableFrom(IfcMetaData.GetType(s.IfcTypeId)) /*&& // !typeof(IfcSpace).IsAssignableFrom(IfcMetaData.GetType(s.IfcTypeId))*/); foreach (var shapeInstance in shapeInstances) { // logging var currentProgress = 100 * prog++ / tot; if (currentProgress != lastProgress && ProgressChanged != null) { ProgressChanged(this, new ProgressChangedEventArgs(currentProgress, "Creating visuals")); lastProgress = currentProgress; // Log.DebugFormat("Progress to {0}% time: {1} seconds", lastProgress, timer.Elapsed.TotalSeconds.ToString("F3")); // Debug.Print("Progress to {0}% time:\t{1} seconds", lastProgress, timer.Elapsed.TotalSeconds.ToString("F3")); } // work out style var styleId = shapeInstance.StyleLabel > 0 ? shapeInstance.StyleLabel : shapeInstance.IfcTypeId * -1; if (!materialsByStyleId.ContainsKey(styleId)) { // if the style is not available we build one by ExpressType var material2 = GetWpfMaterialByType(model, shapeInstance.IfcTypeId); materialsByStyleId.Add(styleId, material2); var mg = GetNewStyleMesh(material2, tmpTransparentsGroup, tmpOpaquesGroup); meshesByStyleId.Add(styleId, mg); } //GET THE ACTUAL GEOMETRY MeshGeometry3D wpfMesh; //see if we have already read it if (UseMaps && repeatedShapeGeometries.TryGetValue(shapeInstance.ShapeGeometryLabel, out wpfMesh)) { var mg = new GeometryModel3D(wpfMesh, materialsByStyleId[styleId]); mg.SetValue(FrameworkElement.TagProperty, new XbimInstanceHandle(model, shapeInstance.IfcProductLabel, shapeInstance.IfcTypeId)); mg.BackMaterial = mg.Material; mg.Transform = XbimMatrix3D.Multiply(shapeInstance.Transformation, modelTransform) .ToMatrixTransform3D(); if (materialsByStyleId[styleId].IsTransparent) { tmpTransparentsGroup.Children.Add(mg); } else { tmpOpaquesGroup.Children.Add(mg); } } else //we need to get the shape geometry { IXbimShapeGeometryData shapeGeom = geomReader.ShapeGeometry(shapeInstance.ShapeGeometryLabel); if (UseMaps && shapeGeom.ReferenceCount > 1) //only store if we are going to use again { wpfMesh = new MeshGeometry3D(); switch ((XbimGeometryType)shapeGeom.Format) { case XbimGeometryType.PolyhedronBinary: wpfMesh.Read(shapeGeom.ShapeData); break; case XbimGeometryType.Polyhedron: wpfMesh.Read(((XbimShapeGeometry)shapeGeom).ShapeData); break; } repeatedShapeGeometries.Add(shapeInstance.ShapeGeometryLabel, wpfMesh); var mg = new GeometryModel3D(wpfMesh, materialsByStyleId[styleId]); mg.SetValue(FrameworkElement.TagProperty, new XbimInstanceHandle(model, shapeInstance.IfcProductLabel, shapeInstance.IfcTypeId)); mg.BackMaterial = mg.Material; mg.Transform = XbimMatrix3D.Multiply(shapeInstance.Transformation, modelTransform).ToMatrixTransform3D(); if (materialsByStyleId[styleId].IsTransparent) { tmpTransparentsGroup.Children.Add(mg); } else { tmpOpaquesGroup.Children.Add(mg); } } else //it is a one off, merge it with shapes of same style { var targetMergeMeshByStyle = meshesByStyleId[styleId]; if (shapeGeom.Format != (byte)XbimGeometryType.PolyhedronBinary) { continue; } var transform = XbimMatrix3D.Multiply(shapeInstance.Transformation, modelTransform); targetMergeMeshByStyle.Add( shapeGeom.ShapeData, shapeInstance.IfcTypeId, shapeInstance.IfcProductLabel, shapeInstance.InstanceLabel, transform, (short)model.UserDefinedId); } } } foreach (var wpfMeshGeometry3D in meshesByStyleId.Values) { wpfMeshGeometry3D.EndUpdate(); } //} if (tmpOpaquesGroup.Children.Any()) { var mv = new ModelVisual3D { Content = tmpOpaquesGroup }; opaqueShapes.Children.Add(mv); // Control.ModelBounds = mv.Content.Bounds.ToXbimRect3D(); } if (tmpTransparentsGroup.Children.Any()) { var mv = new ModelVisual3D { Content = tmpTransparentsGroup }; transparentShapes.Children.Add(mv); //if (Control.ModelBounds.IsEmpty) Control.ModelBounds = mv.Content.Bounds.ToXbimRect3D(); //else Control.ModelBounds.Union(mv.Content.Bounds.ToXbimRect3D()); } } } Log.DebugFormat("Time to load visual components: {0} seconds", timer.Elapsed.TotalSeconds.ToString("F3")); if (ProgressChanged != null) { ProgressChanged(this, new ProgressChangedEventArgs(0, "Ready")); } return(scene); }
public static XbimMeshGeometry3D GetMesh(this XbimModel xbimModel, IEnumerable <IPersistIfcEntity> items, XbimMatrix3D wcsTransform) { var m = new XbimMeshGeometry3D(); if (xbimModel.GeometrySupportLevel == 1) { // this is what happens for version 1 of the engine // foreach (var item in items) { var fromModel = item.ModelOf as XbimModel; if (fromModel == null) { continue; } var geomDataSet = fromModel.GetGeometryData(item.EntityLabel, XbimGeometryType.TriangulatedMesh); foreach (var geomData in geomDataSet) { // todo: add guidance to the TransformBy method so that users can understand how to stop using it (it's marked absolete) geomData.TransformBy(wcsTransform); m.Add(geomData, xbimModel.UserDefinedId); } } } else { // this is what happens for version 2 of the engine // foreach (var item in items) { var fromModel = item.ModelOf as XbimModel; if (fromModel == null || !(item is IfcProduct)) { continue; } var context = new Xbim3DModelContext(fromModel); var productShape = context.ShapeInstancesOf((IfcProduct)item) .Where(s => s.RepresentationType != XbimGeometryRepresentationType.OpeningsAndAdditionsExcluded) .ToList(); // this also returns shapes of voids foreach (var shapeInstance in productShape) { IXbimShapeGeometryData shapeGeom = context.ShapeGeometry(shapeInstance.ShapeGeometryLabel); switch ((XbimGeometryType)shapeGeom.Format) { case XbimGeometryType.PolyhedronBinary: m.Read(shapeGeom.ShapeData, XbimMatrix3D.Multiply(shapeInstance.Transformation, wcsTransform)); break; case XbimGeometryType.Polyhedron: m.Read(((XbimShapeGeometry)shapeGeom).ShapeData, XbimMatrix3D.Multiply(shapeInstance.Transformation, wcsTransform)); break; } } } } return(m); }
/// <summary> /// Exports a gltf file from a meshed model /// </summary> /// <param name="model">The model needs to have the geometry meshes already cached</param> /// <param name="exclude">The types of elements that are going to be omitted (e.g. ifcSpaces).</param> /// <param name="EntityLebels">Only entities in the collection are exported; if null exports the whole model</param> /// <returns></returns> public gltf.Gltf BuildInstancedScene(IModel model, XbimMatrix3D overallTransform, List <Type> exclude = null, HashSet <int> EntityLebels = null) { Init(); Dictionary <int, ShapeComponentIds> geometries = new Dictionary <int, ShapeComponentIds>(); // this needs a previously meshed xbim file. // var s = new Stopwatch(); s.Start(); int iCnt = 0; Random r = new Random(); var excludedTypes = DefaultExclusions(model, exclude); using (var geomStore = model.GeometryStore) using (var geomReader = geomStore.BeginRead()) { // process the materials and styles var sstyleIds = geomReader.StyleIds; foreach (var styleId in sstyleIds) { PrepareStyleMaterial(model, styleId); } int productLabel = 0; var shapeInstances = GetShapeInstancesToRender(geomReader, excludedTypes, EntityLebels); // foreach (var shapeInstance in shapeInstances.OrderBy(x=>x.IfcProductLabel)) gltf.Mesh targetMesh = null; foreach (var shapeInstance in shapeInstances.OrderBy(x => x.IfcProductLabel)) { if (CustomFilter != null) { var skip = CustomFilter(shapeInstance.IfcProductLabel, model); if (skip) { continue; } } // we start with a shape instance and then load its geometry. // a product (e.g. wall or window) in the scene returns: // - a node // - pointing to a mesh, with a transform // - 1 mesh // - with as many mesh primitives as needed to render the different parts // - pointers to the a material and accessors as needed // - 3 accessors per primitive // - vertices, normals, indices // - bufferviews can be reused by different accessors // - data in the buffer, of course if (productLabel != shapeInstance.IfcProductLabel) { // need new product // create node var nodeIndex = _nodes.Count; var entity = model.Instances[shapeInstance.IfcProductLabel] as IIfcProduct; if (entity == null) { // fire error here. } var tnode = new gltf.Node(); tnode.Name = entity.Name + $" #{entity.EntityLabel}"; // instance transformation needs to be expressed in meters // var inModelTransf = XbimMatrix3D.Copy(shapeInstance.Transformation); inModelTransf.OffsetX /= model.ModelFactors.OneMeter; inModelTransf.OffsetY /= model.ModelFactors.OneMeter; inModelTransf.OffsetZ /= model.ModelFactors.OneMeter; // overalltransform is already expressed in meters var tMat = XbimMatrix3D.Multiply(inModelTransf, overallTransform); tnode.Matrix = tMat.ToFloatArray(); // create mesh var meshIndex = _meshes.Count; targetMesh = new gltf.Mesh { Name = $"Instance {productLabel}" }; // link node to mesh tnode.Mesh = meshIndex; // add all to lists _nodes.Add(tnode); _meshes.Add(targetMesh); } // now the geometry // IXbimShapeGeometryData shapeGeom = geomReader.ShapeGeometry(shapeInstance.ShapeGeometryLabel); if (shapeGeom.Format != (byte)XbimGeometryType.PolyhedronBinary) { continue; } // work out colour id; // the colour is associated with the instance, not the geometry. // positives are styles, negatives are types var colId = shapeInstance.StyleLabel > 0 ? shapeInstance.StyleLabel : shapeInstance.IfcTypeId * -1; int materialIndex; if (!styleDic.TryGetValue(colId, out materialIndex)) { // if the style is not available we build one by ExpressType materialIndex = PrepareTypeMaterial(model, shapeInstance.IfcTypeId); styleDic.Add(colId, materialIndex); } // note: at a first investigation it looks like the shapeInstance.Transformation is the same for all shapes of the same product if (shapeGeom.ReferenceCount > 1) { // retain the information to reuse the map multiple times // // if g is not found in the dictionary then build it and add it ShapeComponentIds components; if (!geometries.TryGetValue(shapeGeom.ShapeLabel, out components)) { // mesh var xbimMesher = new XbimMesher(); xbimMesher.AddMesh(shapeGeom.ShapeData); components = AddGeom( xbimMesher.PositionsAsSingleList(model.ModelFactors.OneMeter), xbimMesher.Indices, xbimMesher.NormalsAsSingleList() ); geometries.Add(shapeGeom.ShapeLabel, components); } if (components != null) { // var arr = GetTransformInMeters(model, shapeInstance); AddComponentsToMesh(targetMesh, components, materialIndex); } } else { // repeat the geometry only once // var xbimMesher = new XbimMesher(); xbimMesher.AddMesh(shapeGeom.ShapeData); // var trsf = GetTransformInMeters(model, shapeInstance); var components = AddGeom( xbimMesher.PositionsAsSingleList(model.ModelFactors.OneMeter), xbimMesher.Indices, xbimMesher.NormalsAsSingleList() ); AddComponentsToMesh(targetMesh, components, materialIndex); } iCnt++; if (iCnt % 100 == 0) { Debug.WriteLine($"added {iCnt} elements in {s.ElapsedMilliseconds}ms."); } } } Debug.WriteLine($"added {iCnt} elements in {s.ElapsedMilliseconds}ms."); return(Build()); }
XbimScene <WpfMeshGeometry3D, WpfMaterial> ILayerStyler.BuildScene(IModel model, XbimMatrix3D modelTransform, ModelVisual3D opaqueShapes, ModelVisual3D transparentShapes, List <Type> exclude) { var excludedTypes = model.DefaultExclusions(exclude); var tmpOpaquesGroup = new Model3DGroup(); var retScene = new XbimScene <WpfMeshGeometry3D, WpfMaterial>(model); if (_model.Instances == null || !_model.Instances.Any()) { return(retScene); } // define colours var colours = new Dictionary <LayerGroup, XbimColour>(); colours.Add(LayerGroup.Green, new XbimColour("Green", 0.0, 1.0, 0.0, 0.5)); colours.Add(LayerGroup.Red, new XbimColour("Red", 1.0, 0.0, 0.0, 0.5)); colours.Add(LayerGroup.Amber, new XbimColour("Amber", .5, 0.5, .5, .8)); // actually grey // prepare meshes // var meshes = new List <WpfMeshGeometry3D>(); // this list gets added to the scene at the end. // this dictionary holds the list of meshes that are currently used, as they are filled (in size), // new ones get replaced // var meshDic = new Dictionary <LayerGroup, WpfMeshGeometry3D>(); foreach (var group in colours.Keys) { var newItem = PrepareMesh(colours[group]); meshDic.Add(group, newItem); meshes.Add(newItem); } foreach (var mesh in meshes) { mesh.WpfModel.SetValue(FrameworkElement.TagProperty, mesh); mesh.BeginUpdate(); tmpOpaquesGroup.Children.Add(mesh); } using (var geomStore = model.GeometryStore) { using (var geomReader = geomStore.BeginRead()) { var shapeInstances = geomReader.ShapeInstances .Where(s => s.RepresentationType == XbimGeometryRepresentationType.OpeningsAndAdditionsIncluded && !excludedTypes.Contains(s.IfcTypeId)); foreach (var shapeInstance in shapeInstances) { var ent = _model.Instances[shapeInstance.IfcProductLabel]; var grp = GetLayerGroup(ent); if (grp == LayerGroup.Null) { continue; } if (!UseAmber && grp == LayerGroup.Amber) { continue; } WpfMeshGeometry3D targetMergeMesh; meshDic.TryGetValue(grp, out targetMergeMesh); if (targetMergeMesh == null) { continue; } // replace target mesh beyond suggested size // https://docs.microsoft.com/en-us/dotnet/framework/wpf/graphics-multimedia/maximize-wpf-3d-performance // if (targetMergeMesh.PositionCount > 20000 || targetMergeMesh.TriangleIndexCount > 60000 ) { // end current mesh targetMergeMesh.EndUpdate(); // prepare new one and add to the list var replace = PrepareMesh(colours[grp]); meshes.Add(replace); // swap mesh in dicionary and for this loop meshDic[grp] = replace; targetMergeMesh = replace; // prepare in output replace.WpfModel.SetValue(FrameworkElement.TagProperty, replace); replace.BeginUpdate(); tmpOpaquesGroup.Children.Add(replace); } IXbimShapeGeometryData shapeGeom = geomReader.ShapeGeometry(shapeInstance.ShapeGeometryLabel); if (shapeGeom.Format == (byte)XbimGeometryType.PolyhedronBinary) { var transform = XbimMatrix3D.Multiply(shapeInstance.Transformation, modelTransform); targetMergeMesh.Add( shapeGeom.ShapeData, shapeInstance.IfcTypeId, shapeInstance.IfcProductLabel, shapeInstance.InstanceLabel, transform, (short)model.UserDefinedId); } } } } foreach (var mesh in meshDic.Values) { mesh.EndUpdate(); } if (!tmpOpaquesGroup.Children.Any()) { return(retScene); } var mv = new ModelVisual3D { Content = tmpOpaquesGroup }; opaqueShapes.Children.Add(mv); return(retScene); }
/// <summary> /// This version uses the new Geometry representation /// </summary> /// <param name="model"></param> /// <param name="context"></param> /// <param name="exclude">List of type to exclude, by default excplict openings and spaces are excluded if exclude = null</param> /// <returns></returns> public XbimScene <WpfMeshGeometry3D, WpfMaterial> BuildScene(XbimModel model, Xbim3DModelContext context, List <Type> exclude = null) { var excludedTypes = new HashSet <short>(); if (exclude == null) { exclude = new List <Type>() { typeof(IfcSpace) // , typeof(IfcFeatureElement) } } ; foreach (var excludedT in exclude) { var ifcT = IfcMetaData.IfcType(excludedT); foreach (var exIfcType in ifcT.NonAbstractSubTypes.Select(IfcMetaData.IfcType)) { excludedTypes.Add(exIfcType.TypeId); } } var scene = new XbimScene <WpfMeshGeometry3D, WpfMaterial>(model); if (context == null) { return(scene); } //get a list of all the unique styles var styles = new Dictionary <int, WpfMaterial>(); var repeatedShapeGeometries = new Dictionary <int, MeshGeometry3D>(); var styleMeshSets = new Dictionary <int, WpfMeshGeometry3D>(); var tmpOpaquesGroup = new Model3DGroup(); var tmpTransparentsGroup = new Model3DGroup(); var sstyles = context.SurfaceStyles(); foreach (var style in sstyles) { var wpfMaterial = new WpfMaterial(); wpfMaterial.CreateMaterial(style); styles.Add(style.DefinedObjectId, wpfMaterial); var mg = new WpfMeshGeometry3D(wpfMaterial, wpfMaterial); mg.WpfModel.SetValue(FrameworkElement.TagProperty, mg); styleMeshSets.Add(style.DefinedObjectId, mg); mg.BeginUpdate(); if (style.IsTransparent) { tmpTransparentsGroup.Children.Add(mg); } else { tmpOpaquesGroup.Children.Add(mg); } } if (!styles.Any()) { return(scene); //this should always return something } var shapeInstances = context.ShapeInstances() .Where(s => s.RepresentationType == XbimGeometryRepresentationType.OpeningsAndAdditionsIncluded && !excludedTypes.Contains(s.IfcTypeId)); // !typeof (IfcFeatureElement).IsAssignableFrom(IfcMetaData.GetType(s.IfcTypeId)) /*&& // !typeof(IfcSpace).IsAssignableFrom(IfcMetaData.GetType(s.IfcTypeId))*/); foreach (var shapeInstance in shapeInstances) { var styleId = shapeInstance.StyleLabel > 0 ? shapeInstance.StyleLabel : shapeInstance.IfcTypeId * -1; //GET THE ACTUAL GEOMETRY MeshGeometry3D wpfMesh; //see if we have already read it if (repeatedShapeGeometries.TryGetValue(shapeInstance.ShapeGeometryLabel, out wpfMesh)) { var mg = new GeometryModel3D(wpfMesh, styles[styleId]); mg.SetValue(FrameworkElement.TagProperty, new XbimInstanceHandle(model, shapeInstance.IfcProductLabel, shapeInstance.IfcTypeId)); mg.BackMaterial = mg.Material; mg.Transform = XbimMatrix3D.Multiply(shapeInstance.Transformation, Control.ModelPositions[model].Transfrom).ToMatrixTransform3D(); if (styles[styleId].IsTransparent) { tmpTransparentsGroup.Children.Add(mg); } else { tmpOpaquesGroup.Children.Add(mg); } } else //we need to get the shape geometry { IXbimShapeGeometryData shapeGeom = context.ShapeGeometry(shapeInstance.ShapeGeometryLabel); if (shapeGeom.ReferenceCount > 1) //only store if we are going to use again { wpfMesh = new MeshGeometry3D(); switch ((XbimGeometryType)shapeGeom.Format) { case XbimGeometryType.PolyhedronBinary: wpfMesh.Read(shapeGeom.ShapeData); break; case XbimGeometryType.Polyhedron: wpfMesh.Read(((XbimShapeGeometry)shapeGeom).ShapeData); break; } repeatedShapeGeometries.Add(shapeInstance.ShapeGeometryLabel, wpfMesh); var mg = new GeometryModel3D(wpfMesh, styles[styleId]); mg.SetValue(FrameworkElement.TagProperty, new XbimInstanceHandle(model, shapeInstance.IfcProductLabel, shapeInstance.IfcTypeId)); mg.BackMaterial = mg.Material; mg.Transform = XbimMatrix3D.Multiply(shapeInstance.Transformation, Control.ModelPositions[model].Transfrom).ToMatrixTransform3D(); if (styles[styleId].IsTransparent) { tmpTransparentsGroup.Children.Add(mg); } else { tmpOpaquesGroup.Children.Add(mg); } } else //it is a one off, merge it with shapes of a similar material { var targetMergeMeshByStyle = styleMeshSets[styleId]; switch ((XbimGeometryType)shapeGeom.Format) { case XbimGeometryType.Polyhedron: // var shapePoly = (XbimShapeGeometry)shapeGeom; var asString = Encoding.UTF8.GetString(shapeGeom.ShapeData.ToArray()); targetMergeMeshByStyle.Add( asString, shapeInstance.IfcTypeId, shapeInstance.IfcProductLabel, shapeInstance.InstanceLabel, XbimMatrix3D.Multiply(shapeInstance.Transformation, Control.ModelPositions[model].Transfrom), model.UserDefinedId); break; case XbimGeometryType.PolyhedronBinary: var transform = XbimMatrix3D.Multiply(shapeInstance.Transformation, Control.ModelPositions[model].Transfrom); targetMergeMeshByStyle.Add( shapeGeom.ShapeData, shapeInstance.IfcTypeId, shapeInstance.IfcProductLabel, shapeInstance.InstanceLabel, transform, model.UserDefinedId); break; default: throw new ArgumentOutOfRangeException(); } } } } foreach (var wpfMeshGeometry3D in styleMeshSets.Values) { wpfMeshGeometry3D.EndUpdate(); } //} if (tmpOpaquesGroup.Children.Any()) { var mv = new ModelVisual3D(); mv.Content = tmpOpaquesGroup; Control.OpaquesVisual3D.Children.Add(mv); // Control.ModelBounds = mv.Content.Bounds.ToXbimRect3D(); } if (tmpTransparentsGroup.Children.Any()) { var mv = new ModelVisual3D(); mv.Content = tmpTransparentsGroup; Control.TransparentsVisual3D.Children.Add(mv); //if (Control.ModelBounds.IsEmpty) Control.ModelBounds = mv.Content.Bounds.ToXbimRect3D(); //else Control.ModelBounds.Union(mv.Content.Bounds.ToXbimRect3D()); } return(scene); }
private void WriteGeometry(JsonWriter writer) { XbimMatrix3D globalTrans = GetGlobalModelTransform(); //write out the material nodes and then the instances for each material Dictionary <int, XbimTexture> styles = _context.SurfaceStyles().ToDictionary(s => s.DefinedObjectId); foreach (var instanceGroup in _context.ShapeInstancesGroupByStyle()) { if (!instanceGroup.Any()) { continue; //skip emmpty instances; } int styleId = instanceGroup.Key; XbimTexture style = styles[styleId]; writer.WriteStartObject(); //Material node { writer.WritePropertyName("type"); writer.WriteValue("material"); writer.WritePropertyName("id"); writer.WriteValue("M" + styleId); writer.WritePropertyName("color"); writer.WriteStartObject(); //begin color { writer.WritePropertyName("r"); writer.WriteValue(style.ColourMap[0].Red); writer.WritePropertyName("g"); writer.WriteValue(style.ColourMap[0].Green); writer.WritePropertyName("b"); writer.WriteValue(style.ColourMap[0].Blue); } writer.WriteEndObject(); //end color writer.WritePropertyName("alpha"); writer.WriteValue(style.ColourMap[0].Alpha); //all instances of this style writer.WritePropertyName("nodes"); //beginning of the instance nodes writer.WriteStartArray(); foreach (var shapeInstance in instanceGroup) { writer.WriteStartObject(); //start of instance transform { if (_maps.Contains(shapeInstance.ShapeGeometryLabel)) //it is a reference { //write the transform writer.WritePropertyName("type"); //geometry node writer.WriteValue("matrix"); writer.WritePropertyName("id"); writer.WriteValue("I" + shapeInstance.InstanceLabel); writer.WritePropertyName("elements"); XbimMatrix3D m = XbimMatrix3D.Multiply(shapeInstance.Transformation, globalTrans); WriteMatrix(writer, m); writer.WritePropertyName("nodes"); //beginning of the instance nodes writer.WriteStartArray(); //write the map writer.WriteStartObject(); //start of map { writer.WritePropertyName("type"); //geometry node writer.WriteValue("geometry"); writer.WritePropertyName("coreId"); writer.WriteValue("L" + shapeInstance.ShapeGeometryLabel); } writer.WriteEndObject(); //end of map writer.WriteEndArray(); //end of instance tranform nodes } else //write the actual geometry { writer.WritePropertyName("type"); //geometry node writer.WriteValue("geometry"); writer.WritePropertyName("primitive"); //primitive: " writer.WriteValue("triangles"); writer.WritePropertyName("id"); writer.WriteValue("I" + shapeInstance.InstanceLabel); WriteShapeGeometry(writer, _context.ShapeGeometry(shapeInstance), XbimMatrix3D.Multiply(shapeInstance.Transformation, globalTrans)); } } writer.WriteEndObject(); //end of instance transform } writer.WriteEndArray(); //end of instance transform nodes } writer.WriteEndObject(); // end of the material node } }
XbimScene <WpfMeshGeometry3D, WpfMaterial> ILayerStyler.BuildScene(IModel model, XbimMatrix3D modelTransform, ModelVisual3D opaqueShapes, ModelVisual3D transparentShapes, List <Type> exclude) { var excludedTypes = model.DefaultExclusions(exclude); var tmpOpaquesGroup = new Model3DGroup(); var retScene = new XbimScene <WpfMeshGeometry3D, WpfMaterial>(model); var meshes = new List <WpfMeshGeometry3D>(); if (_discriminator == null) { _discriminator = new VisualDiscriminator(_window.Doc); } if (_model.Instances == null || !_model.Instances.Any()) { return(retScene); } var red = PrepareMesh(_colourFail); meshes.Add(red); var green = PrepareMesh(_colourPass); meshes.Add(green); var blue = PrepareMesh(_colourNa); meshes.Add(blue); var amber = PrepareMesh(_colourWarning); meshes.Add(amber); foreach (var mesh in meshes) { mesh.WpfModel.SetValue(FrameworkElement.TagProperty, mesh); mesh.BeginUpdate(); tmpOpaquesGroup.Children.Add(mesh); } using (var geomStore = model.GeometryStore) { using (var geomReader = geomStore.BeginRead()) { var shapeInstances = geomReader.ShapeInstances .Where(s => s.RepresentationType == XbimGeometryRepresentationType.OpeningsAndAdditionsIncluded && !excludedTypes.Contains(s.IfcTypeId)); foreach (var shapeInstance in shapeInstances) { var ent = _model.Instances[shapeInstance.IfcProductLabel]; var grp = _discriminator.GetLayerGroup(ent); if (grp == VisualDiscriminator.LayerGroup.Null) { continue; } if (!UseBlue && grp == VisualDiscriminator.LayerGroup.Blue) { continue; } if (!UseAmber && grp == VisualDiscriminator.LayerGroup.Amber) { continue; } WpfMeshGeometry3D targetMergeMesh = null; switch (grp) { case VisualDiscriminator.LayerGroup.Red: targetMergeMesh = red; break; case VisualDiscriminator.LayerGroup.Green: targetMergeMesh = green; break; case VisualDiscriminator.LayerGroup.Blue: targetMergeMesh = blue; break; case VisualDiscriminator.LayerGroup.Amber: targetMergeMesh = amber; break; } if (targetMergeMesh == null) { continue; } IXbimShapeGeometryData shapeGeom = geomReader.ShapeGeometry(shapeInstance.ShapeGeometryLabel); if (shapeGeom.Format == (byte)XbimGeometryType.PolyhedronBinary) { var transform = XbimMatrix3D.Multiply(shapeInstance.Transformation, modelTransform); targetMergeMesh.Add( shapeGeom.ShapeData, shapeInstance.IfcTypeId, shapeInstance.IfcProductLabel, shapeInstance.InstanceLabel, transform, (short)model.UserDefinedId); } } } } foreach (var mesh in meshes) { mesh.EndUpdate(); } if (!tmpOpaquesGroup.Children.Any()) { return(retScene); } var mv = new ModelVisual3D { Content = tmpOpaquesGroup }; opaqueShapes.Children.Add(mv); // no transparents are present //if (tmpTransparentsGroup.Children.Any()) //{ // var mv = new ModelVisual3D { Content = tmpTransparentsGroup }; // transparentShapes.Children.Add(mv); //} return(retScene); }
/// <summary> /// This version uses the new Geometry representation /// </summary> /// <param name="model"></param> /// <param name="modelTransform">The transform to place the models geometry in the right place</param> /// <param name="opaqueShapes"></param> /// <param name="transparentShapes"></param> /// <param name="isolateInstances">List of instances to be isolated</param> /// <param name="hideInstances">List of instances to be hidden</param> /// <param name="excludeTypes">List of type to exclude, by default excplict openings and spaces are excluded if exclude = null</param> /// <returns></returns> public XbimScene <WpfMeshGeometry3D, WpfMaterial> BuildScene(IModel model, XbimMatrix3D modelTransform, ModelVisual3D opaqueShapes, ModelVisual3D transparentShapes, List <IPersistEntity> isolateInstances = null, List <IPersistEntity> hideInstances = null, List <Type> excludeTypes = null) { var excludedTypes = model.DefaultExclusions(excludeTypes); var onlyInstances = isolateInstances?.Where(i => i.Model == model).ToDictionary(i => i.EntityLabel); var hiddenInstances = hideInstances?.Where(i => i.Model == model).ToDictionary(i => i.EntityLabel); var scene = new XbimScene <WpfMeshGeometry3D, WpfMaterial>(model); var timer = new Stopwatch(); timer.Start(); using (var geomStore = model.GeometryStore) { using (var geomReader = geomStore.BeginRead()) { // we are keeping the style to decide if a new element needs to be transparent. // var materialsByStyleId = new Dictionary <int, WpfMaterial>(); var repeatedShapeGeometries = new Dictionary <int, MeshGeometry3D>(); var tmpOpaquesGroup = new Model3DGroup(); var tmpTransparentsGroup = new Model3DGroup(); //get a list of all the unique style ids then build their style and mesh // var sstyleIds = geomReader.StyleIds; foreach (var styleId in sstyleIds) { var wpfMaterial = GetWpfMaterial(model, styleId); materialsByStyleId.Add(styleId, wpfMaterial); } var shapeInstances = GetShapeInstancesToRender(geomReader, excludedTypes); var tot = 1; if (ProgressChanged != null) { // only enumerate if there's a need for progress update tot = shapeInstances.Count(); } var prog = 0; var lastProgress = 0; // !typeof (IfcFeatureElement).IsAssignableFrom(IfcMetaData.GetType(s.IfcTypeId)) /*&& // !typeof(IfcSpace).IsAssignableFrom(IfcMetaData.GetType(s.IfcTypeId))*/); // foreach (var shapeInstance in shapeInstances .Where(s => null == onlyInstances || onlyInstances.Count == 0 || onlyInstances.Keys.Contains(s.IfcProductLabel)) .Where(s => null == hiddenInstances || hiddenInstances.Count == 0 || !hiddenInstances.Keys.Contains(s.IfcProductLabel))) { int id = shapeInstance.IfcProductLabel; //LINKS TO ACTUAL ELEMENT ShadedElement el = elements[id]; var i = model.Instances[id]; // logging var currentProgress = 100 * prog++ / tot; if (currentProgress != lastProgress && ProgressChanged != null) { ProgressChanged(this, new ProgressChangedEventArgs(currentProgress, "Creating visuals")); lastProgress = currentProgress; } // work out style var styleId = shapeInstance.StyleLabel > 0 ? shapeInstance.StyleLabel : shapeInstance.IfcTypeId * -1; WpfMaterial selectedMaterial; if (!materialsByStyleId.TryGetValue(styleId, out selectedMaterial)) { // if the style is not available we build one by ExpressType selectedMaterial = GetWpfMaterialByType(model, shapeInstance.IfcTypeId); materialsByStyleId.Add(styleId, selectedMaterial); } int colorIndex = (int)el.currCriticality; selectedMaterial = new WpfMaterial(colsPerCriticality[colorIndex]); //GET THE ACTUAL GEOMETRY MeshGeometry3D wpfMesh; //see if we have already read it if (!repeatedShapeGeometries.TryGetValue(shapeInstance.ShapeGeometryLabel, out wpfMesh)) { IXbimShapeGeometryData shapeGeom = geomReader.ShapeGeometry(shapeInstance.ShapeGeometryLabel); if ((XbimGeometryType)shapeGeom.Format != XbimGeometryType.PolyhedronBinary) { continue; } wpfMesh = new MeshGeometry3D(); wpfMesh.Read(shapeGeom.ShapeData); if (shapeGeom.ReferenceCount > 1) //only store if we are going to use again { repeatedShapeGeometries.Add(shapeInstance.ShapeGeometryLabel, wpfMesh); } } var mg = new GeometryModel3D(wpfMesh, selectedMaterial); mg.BackMaterial = mg.Material; mg.SetValue(FrameworkElement.TagProperty, new XbimInstanceHandle(model, shapeInstance.IfcProductLabel, shapeInstance.IfcTypeId)); mg.Transform = XbimMatrix3D.Multiply(shapeInstance.Transformation, modelTransform).ToMatrixTransform3D(); if (materialsByStyleId[styleId].IsTransparent) { tmpTransparentsGroup.Children.Add(mg); } else { tmpOpaquesGroup.Children.Add(mg); } } if (tmpOpaquesGroup.Children.Any()) { var mv = new ModelVisual3D { Content = tmpOpaquesGroup }; opaqueShapes.Children.Add(mv); } if (tmpTransparentsGroup.Children.Any()) { var mv = new ModelVisual3D { Content = tmpTransparentsGroup }; transparentShapes.Children.Add(mv); } } } Logger.LogDebug("Time to load visual components: {0:F3} seconds", timer.Elapsed.TotalSeconds); ProgressChanged?.Invoke(this, new ProgressChangedEventArgs(0, "Ready")); return(scene); }
/// <summary> /// This version uses the new Geometry representation /// </summary> /// <param name="model"></param> /// <param name="modelTransform">The transform to place the models geometry in the right place</param> /// <param name="opaqueShapes"></param> /// <param name="transparentShapes"></param> /// <param name="exclude">List of type to exclude, by default excplict openings and spaces are excluded if exclude = null</param> /// <returns></returns> public XbimScene <WpfMeshGeometry3D, WpfMaterial> BuildScene(IModel model, XbimMatrix3D modelTransform, ModelVisual3D opaqueShapes, ModelVisual3D transparentShapes, List <Type> exclude = null) { var excludedTypes = model.DefaultExclusions(exclude); var scene = new XbimScene <WpfMeshGeometry3D, WpfMaterial>(model); var timer = new Stopwatch(); timer.Start(); using (var geomStore = model.GeometryStore) { using (var geomReader = geomStore.BeginRead()) { var materialsByStyleId = new Dictionary <int, WpfMaterial>(); var repeatedShapeGeometries = new Dictionary <int, MeshGeometry3D>(); var meshesByStyleId = new Dictionary <int, WpfMeshGeometry3D>(); var tmpOpaquesGroup = new Model3DGroup(); var tmpTransparentsGroup = new Model3DGroup(); //get a list of all the unique style ids then build their style and mesh var sstyleIds = geomReader.StyleIds; foreach (var styleId in sstyleIds) { var wpfMaterial = GetWpfMaterial(model, styleId); materialsByStyleId.Add(styleId, wpfMaterial); var mg = GetNewStyleMesh(wpfMaterial, tmpTransparentsGroup, tmpOpaquesGroup); meshesByStyleId.Add(styleId, mg); } var shapeInstances = GetShapeInstancesToRender(geomReader, excludedTypes); var tot = 1; if (ProgressChanged != null) { // only enumerate if there's a need for progress update tot = shapeInstances.Count(); } var prog = 0; var lastProgress = 0; // !typeof (IfcFeatureElement).IsAssignableFrom(IfcMetaData.GetType(s.IfcTypeId)) /*&& // !typeof(IfcSpace).IsAssignableFrom(IfcMetaData.GetType(s.IfcTypeId))*/); foreach (var shapeInstance in shapeInstances) { // logging var currentProgress = 100 * prog++ / tot; if (currentProgress != lastProgress && ProgressChanged != null) { ProgressChanged(this, new ProgressChangedEventArgs(currentProgress, "Creating visuals")); lastProgress = currentProgress; } // work out style var styleId = shapeInstance.StyleLabel > 0 ? shapeInstance.StyleLabel : shapeInstance.IfcTypeId * -1; if (!materialsByStyleId.ContainsKey(styleId)) { // if the style is not available we build one by ExpressType var material2 = GetWpfMaterialByType(model, shapeInstance.IfcTypeId); materialsByStyleId.Add(styleId, material2); var mg = GetNewStyleMesh(material2, tmpTransparentsGroup, tmpOpaquesGroup); meshesByStyleId.Add(styleId, mg); } //GET THE ACTUAL GEOMETRY MeshGeometry3D wpfMesh; //see if we have already read it if (UseMaps && repeatedShapeGeometries.TryGetValue(shapeInstance.ShapeGeometryLabel, out wpfMesh)) { var mg = new GeometryModel3D(wpfMesh, materialsByStyleId[styleId]); mg.SetValue(FrameworkElement.TagProperty, new XbimInstanceHandle(model, shapeInstance.IfcProductLabel, shapeInstance.IfcTypeId)); mg.BackMaterial = mg.Material; mg.Transform = XbimMatrix3D.Multiply(shapeInstance.Transformation, modelTransform) .ToMatrixTransform3D(); if (materialsByStyleId[styleId].IsTransparent) { tmpTransparentsGroup.Children.Add(mg); } else { tmpOpaquesGroup.Children.Add(mg); } } else //we need to get the shape geometry { IXbimShapeGeometryData shapeGeom = geomReader.ShapeGeometry(shapeInstance.ShapeGeometryLabel); if (UseMaps && shapeGeom.ReferenceCount > 1) //only store if we are going to use again { wpfMesh = new MeshGeometry3D(); switch ((XbimGeometryType)shapeGeom.Format) { case XbimGeometryType.PolyhedronBinary: wpfMesh.Read(shapeGeom.ShapeData); break; case XbimGeometryType.Polyhedron: wpfMesh.Read(((XbimShapeGeometry)shapeGeom).ShapeData); break; } repeatedShapeGeometries.Add(shapeInstance.ShapeGeometryLabel, wpfMesh); var mg = new GeometryModel3D(wpfMesh, materialsByStyleId[styleId]); mg.SetValue(FrameworkElement.TagProperty, new XbimInstanceHandle(model, shapeInstance.IfcProductLabel, shapeInstance.IfcTypeId)); mg.BackMaterial = mg.Material; mg.Transform = XbimMatrix3D.Multiply(shapeInstance.Transformation, modelTransform).ToMatrixTransform3D(); if (materialsByStyleId[styleId].IsTransparent) { tmpTransparentsGroup.Children.Add(mg); } else { tmpOpaquesGroup.Children.Add(mg); } } else //it is a one off, merge it with shapes of same style { var targetMergeMeshByStyle = meshesByStyleId[styleId]; // replace target mesh beyond suggested size // https://docs.microsoft.com/en-us/dotnet/framework/wpf/graphics-multimedia/maximize-wpf-3d-performance // if (targetMergeMeshByStyle.PositionCount > 20000 || targetMergeMeshByStyle.TriangleIndexCount > 60000 ) { targetMergeMeshByStyle.EndUpdate(); var replace = GetNewStyleMesh(materialsByStyleId[styleId], tmpTransparentsGroup, tmpOpaquesGroup); meshesByStyleId[styleId] = replace; targetMergeMeshByStyle = replace; } // end replace if (shapeGeom.Format != (byte)XbimGeometryType.PolyhedronBinary) { continue; } var transform = XbimMatrix3D.Multiply(shapeInstance.Transformation, modelTransform); targetMergeMeshByStyle.Add( shapeGeom.ShapeData, shapeInstance.IfcTypeId, shapeInstance.IfcProductLabel, shapeInstance.InstanceLabel, transform, (short)model.UserDefinedId); } } } foreach (var wpfMeshGeometry3D in meshesByStyleId.Values) { wpfMeshGeometry3D.EndUpdate(); } if (tmpOpaquesGroup.Children.Any()) { var mv = new ModelVisual3D { Content = tmpOpaquesGroup }; opaqueShapes.Children.Add(mv); } if (tmpTransparentsGroup.Children.Any()) { var mv = new ModelVisual3D { Content = tmpTransparentsGroup }; transparentShapes.Children.Add(mv); } } } Log.DebugFormat("Time to load visual components: {0:F3} seconds", timer.Elapsed.TotalSeconds); ProgressChanged?.Invoke(this, new ProgressChangedEventArgs(0, "Ready")); return(scene); }
public BimStore3DModel Load(string fileName) { var bimStoreItems = new Dictionary <IPersistEntity, List <Tuple <MeshGeometry3D, MaterialModel, XbimMatrix3D> > > (); //ID - ifcProductLabel var ifcModel = IfcStore.Open(fileName, null, null, (progress, state) => { reportProgress?.Invoke(progress, state); }, XbimDBAccess.Exclusive); //Prepare var modelPosition = new XbimModelPositioning(ifcModel); var context = new Xbim3DModelContext(ifcModel); context.CreateContext(); //Clear materials MaterialManager.Clear(); var materialsByStyleId = new Dictionary <int, MaterialModel>(); var excludedTypes = GenerateDefaultExclusions(ifcModel, DefaultExcludedTypes); using (var geometryStore = ifcModel.ReferencingModel.GeometryStore) { using (var geometryReader = geometryStore.BeginRead()) { var shapeInstances = GetShapeInstancesToRender(geometryReader, excludedTypes); foreach (var shapeInstance in shapeInstances) { #region Material var styleId = shapeInstance.StyleLabel > 0 ? shapeInstance.StyleLabel : shapeInstance.IfcTypeId * -1; MaterialModel material; if (!materialsByStyleId.ContainsKey(styleId)) { material = MaterialModelCreator.Create(ifcModel, shapeInstance.IfcTypeId); materialsByStyleId.Add(styleId, material); MaterialManager.Add(material); } else { material = materialsByStyleId[styleId]; } #endregion #region Geometry IXbimShapeGeometryData shapeGeometry = geometryReader.ShapeGeometry(shapeInstance.ShapeGeometryLabel); var geometry3D = new MeshGeometry3D(); switch ((XbimGeometryType)shapeGeometry.Format) { case XbimGeometryType.PolyhedronBinary: geometry3D.Read(shapeGeometry.ShapeData); break; case XbimGeometryType.Polyhedron: geometry3D.Read(((XbimShapeGeometry)shapeGeometry).ShapeData); break; } #endregion var ifcProduct = ifcModel.Model.Instances.FirstOrDefault(i => i.EntityLabel == shapeInstance.IfcProductLabel); if (ifcProduct != null) { if (!bimStoreItems.ContainsKey(ifcProduct)) { bimStoreItems.Add(ifcProduct, new List <Tuple <MeshGeometry3D, MaterialModel, XbimMatrix3D> >(new [] { new Tuple <MeshGeometry3D, MaterialModel, XbimMatrix3D>(geometry3D, material, XbimMatrix3D.Multiply(modelPosition.Transform, shapeInstance.Transformation)), })); } else { bimStoreItems[ifcProduct].Add(new Tuple <MeshGeometry3D, MaterialModel, XbimMatrix3D>(geometry3D, material, XbimMatrix3D.Multiply(modelPosition.Transform, shapeInstance.Transformation))); } } } } } //Generate model var bimStore3D = new BimStore3DModel(context.Model as IfcStore); foreach (var bimStoreItem in bimStoreItems) { bimStore3D.Add( new BimStoreItem3DModel(bimStoreItem.Key, new List <BimGeometry3DModel>( bimStoreItem.Value.Select(x => new BimGeometry3DModel( x.Item1.ToMeshModel(), x.Item2, x.Item3.ToMatrix3D()))))); } return(bimStore3D); }