private WpfMeshGeometry3D PrepareMesh(XbimColour col)
 {
     var matRed = new WpfMaterial();
     matRed.CreateMaterial(col);
     var mg = new WpfMeshGeometry3D(matRed, matRed);
     return mg;
 }
Exemplo n.º 2
0
        protected static WpfMeshGeometry3D GetNewStyleMesh(WpfMaterial wpfMaterial, Model3DGroup tmpTransparentsGroup,
                                                           Model3DGroup tmpOpaquesGroup)
        {
            var mg = new WpfMeshGeometry3D(wpfMaterial, wpfMaterial);

            mg.WpfModel.SetValue(FrameworkElement.TagProperty, mg);
            mg.BeginUpdate();
            if (wpfMaterial.IsTransparent)
            {
                tmpTransparentsGroup.Children.Add(mg);
            }
            else
            {
                tmpOpaquesGroup.Children.Add(mg);
            }
            return(mg);
        }
Exemplo n.º 3
0
        protected static WpfMeshGeometry3D GetNewStyleMesh(WpfMaterial wpfMaterial, Model3DGroup tmpTransparentsGroup,
                                                           Model3DGroup tmpOpaquesGroup)
        {
            var mg = new WpfMeshGeometry3D(wpfMaterial, wpfMaterial, wpfMaterial.IfcTextureCoordinate);

            // set the tag of the child of mg to mg, so that it can be identified on click
            mg.WpfModel.SetValue(FrameworkElement.TagProperty, mg);
            mg.BeginUpdate();
            if (wpfMaterial.IsTransparent)
            {
                tmpTransparentsGroup.Children.Add(mg);
            }
            else
            {
                tmpOpaquesGroup.Children.Add(mg);
            }
            return(mg);
        }
        protected WpfMaterial GetWpfMaterial(IModel model, int styleId)
        {
            var sStyle  = model.Instances[styleId] as IIfcSurfaceStyle;
            var texture = XbimTexture.Create(sStyle);

            if (texture.ColourMap.Count > 0)
            {
                if (texture.ColourMap[0].Alpha <= 0)
                {
                    texture.ColourMap[0].Alpha = 0.5f;
                    Logger.LogWarning("Fully transparent style #{styleId} forced to 50% opacity.", styleId);
                }
            }

            texture.DefinedObjectId = styleId;
            var wpfMaterial = new WpfMaterial();

            wpfMaterial.CreateMaterial(texture);
            return(wpfMaterial);
        }
        /// <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);
        }
Exemplo n.º 6
0
        public CustomShaderMaterialSample()
        {
            InitializeComponent();

            _disposeList = new DisposeList();


            // Load Stanford bunny 3D model
            var readerObj    = new Ab3d.ReaderObj();
            var bunnyModel3D = readerObj.ReadModel3D(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources\\Models\\bun_zipper_res3.obj"));

            // Get MeshGeometry3D

            var geometryModel3D = bunnyModel3D as GeometryModel3D;

            if (geometryModel3D != null)
            {
                _meshGeometry3D = geometryModel3D.Geometry as MeshGeometry3D;
            }
            else
            {
                _meshGeometry3D = null;
            }

            if (_meshGeometry3D == null)
            {
                return;
            }


            // Add 4 models with MeshNormalMaterial
            AddMeshNormalMaterialModel(_meshGeometry3D, new Point3D(-0.3, 0, 0), new Color3(1.0f, 1.0f, 1.0f));

            AddMeshNormalMaterialModel(_meshGeometry3D, new Point3D(-0.1, 0, 0), new Color3(1.0f, 0.0f, 0.0f));
            AddMeshNormalMaterialModel(_meshGeometry3D, new Point3D(0.1, 0, 0), new Color3(0.0f, 1.0f, 0.0f));
            AddMeshNormalMaterialModel(_meshGeometry3D, new Point3D(0.3, 0, 0), new Color3(0.0f, 0.0f, 1.0f));


            // Behind those 4 bunnies we add one bunny with standard WPF material:
            AddStandardModel(_meshGeometry3D, new Point3D(-0.2, 0, -0.3), new DiffuseMaterial(Brushes.LightSlateGray));

            // And then add one with standard WPF material but with overridden Effect - this is done inside the DXSceneDeviceCreated event handler (because we need an instance of MeshNormalEffect)


            // We use DXViewportView.DXSceneDeviceCreated to:
            // 1) Register DirectoryShaderBytecodeProvider that will provide shaders from local folder
            // 2) Create a bunny with overridden effect
            MainDXViewportView.DXSceneDeviceCreated += delegate(object sender, EventArgs args)
            {
                var dxScene = MainDXViewportView.DXScene;

                // DirectoryShaderBytecodeProvider will provide easy access to shaders that are stored in a local folder.
                // In case the shaders are stored in assembly as EmbeddedResources, you can also use AssemblyShaderBytecodeProvider (another option is to use DictionaryShaderBytecodeProvider)
                string shadersFolder = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources\\Shaders");
                var    directoryShaderBytecodeProvider = new DirectoryShaderBytecodeProvider(shadersFolder);

                // We register the directoryShaderBytecodeProvider by EffectsManager.
                // This way we can use GetVertexShader, GetPixelShader, GetShaders and other methods to simply create the shaders.
                // This also gives us flexibility because we can move shaders to other location later without the need to update the code in the Effect (update the location of the shaders).
                dxScene.DXDevice.EffectsManager.RegisterShaderResource(directoryShaderBytecodeProvider);


                // To override the effect, we first need to get an instance of MeshNormalEffect
                _wpfMaterialEffect = dxScene.DXDevice.EffectsManager.GetEffect <MeshNormalEffect>();

                if (_wpfMaterialEffect != null)
                {
                    // Create standard GeometryModel3D
                    var model3D = AddStandardModel(_meshGeometry3D, new Point3D(0.2, 0, -0.3), new DiffuseMaterial(Brushes.LightSlateGray));

                    // Add standard WPF effects are converted into WpfMaterial before they can be used in DXEngine.
                    // WpfMaterial will read all WPF material properties and write them into DXEngine's material properties.
                    var wpfMaterial = new WpfMaterial(model3D.Material);

                    // To render this model with providing standard WPF material data (diffuse color, etc.) and
                    // render the model with custom effect, we set the Effect property.
                    // This can be used when you do not need custom material properties and just want to provide custom rendering of standard materials.
                    // Though, it is recommended that in case of custom effect, you create a custom Material class (to use standard properties, you can derive the class from Ab3d.DirectX.Materials.StandardMaterial)
                    wpfMaterial.Effect = _wpfMaterialEffect;

                    model3D.Material.SetUsedDXMaterial(wpfMaterial);
                }
            };

            this.Unloaded += delegate(object sender, RoutedEventArgs args)
            {
                if (_wpfMaterialEffect != null)
                {
                    _wpfMaterialEffect.Dispose();
                    _wpfMaterialEffect = null;
                }

                _disposeList.Dispose();
            };

            LoadShaderText();
        }
Exemplo n.º 7
0
        /// <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 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
            int i = 0;
            var shapeInstances = context.ShapeInstances()
                .Where(s => s.RepresentationType == XbimGeometryRepresentationType.OpeningsAndAdditionsIncluded &&
                            !typeof (IfcFeatureElement).IsAssignableFrom(IfcMetaData.GetType(s.IfcTypeId)) /*&&
                        !typeof(IfcSpace).IsAssignableFrom(IfcMetaData.GetType(s.IfcTypeId))*/);
            foreach (var shapeInstance in shapeInstances)
            {
                Console.WriteLine(i++);
                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.WcsTransform).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.WcsTransform).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;
                                targetMergeMeshByStyle.Add(
                           shapePoly.ShapeData,
                           shapeInstance.IfcTypeId,
                           shapeInstance.IfcProductLabel,
                           shapeInstance.InstanceLabel,
                           XbimMatrix3D.Multiply(shapeInstance.Transformation, Control.WcsTransform));
                                break;

                            case XbimGeometryType.PolyhedronBinary:
                                targetMergeMeshByStyle.Add(
                          shapeGeom.ShapeData,
                          shapeInstance.IfcTypeId,
                          shapeInstance.IfcProductLabel,
                          shapeInstance.InstanceLabel,
                          XbimMatrix3D.Multiply(shapeInstance.Transformation, Control.WcsTransform));
                                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.Opaques.Children.Add(mv);
                Control.ModelBounds = mv.Content.Bounds.ToXbimRect3D();
            }
            if (tmpTransparentsGroup.Children.Any())
            {
                var mv = new ModelVisual3D();
                mv.Content = tmpTransparentsGroup;
                Control.Transparents.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 ShowGeometryModel3D(GeometryModel3D model3D, float pixelSize)
        {
            MainViewport.Children.Clear();
            _disposables.Dispose();           // Dispose previously used resources

            _disposables = new DisposeList(); // Start with a fresh DisposeList

            if (_pixelEffect == null)
            {
                // Get an instance of PixelEffect (it is used to provide the correct shaders to render specified postions as pixels)
                _pixelEffect = MainDXViewportView.DXScene.DXDevice.EffectsManager.GetEffect <PixelEffect>(createNewEffectInstanceIfNotFound: true);

                // Do not forget to dispose the effect when it is not used any more - we will do that in the Unloaded event handler
            }


            // We will render the GeometryModel3D with overriding the usage of standard effect
            // that renders DiffuseMaterial and other standard materials
            // with custom effect: PixelEffect.
            // This will use different shaders to render the provided triangles.
            //
            // Because the standard material does not provide pixel size,
            // we need to set the fallback pixel size value to the PixelEffect.
            _pixelEffect.PixelSize = pixelSize;


            // To override the used material, we first need to create a new WpfMaterial from the WPF material.
            var wpfMaterial = new WpfMaterial(model3D.Material);

            // then set the Effect to it ...
            wpfMaterial.Effect = _pixelEffect;

            // and finally specify the WpfMaterial to be used whenever the model3D.Material is used.
            model3D.Material.SetUsedDXMaterial(wpfMaterial);

            _disposables.Add(wpfMaterial);


            // Now just add the model3D to the MainViewport
            var modelVisual3D = new ModelVisual3D();

            modelVisual3D.Content = model3D;

            MainViewport.Children.Add(modelVisual3D);


            // IMPORTANT:
            // The above method of showing 3D model with pixels is not optimal.
            // The reason for this is that this way the pixles are rendered for each triangle in the model.
            // But because the same positions are usually used by multiple triangles, those positions will be rendered multiple times.
            //
            // A better way to render the models is to extract the positions from MeshGeometry3D
            // and render the pixels are a list of positions.
            // This is shown in the commented code below:
            //
            // The code above is provided to also show a way to render a 3D model with a different effect.

            //var meshGeometry3D = (MeshGeometry3D)model3D.Geometry;
            //var positions = meshGeometry3D.Positions;
            //var positionsCount = positions.Count;

            //var positionsArray = new Vector3[positionsCount];

            //if (model3D.Transform == null || model3D.Transform.Value.IsIdentity)
            //{
            //    for (int i = 0; i < positionsCount; i++)
            //        positionsArray[i] = positions[i].ToVector3();
            //}
            //else
            //{
            //    for (int i = 0; i < positionsCount; i++)
            //        positionsArray[i] = model3D.Transform.Transform(positions[i]).ToVector3();
            //}

            //// Extract pixel color from material (use Red as fallback)
            //Color4 pixelColor = Colors.Red.ToColor4();
            //var diffuseMaterial = model3D.Material as DiffuseMaterial;
            //if (diffuseMaterial != null)
            //{
            //    var solidColorBrush = diffuseMaterial.Brush as SolidColorBrush;
            //    if (solidColorBrush != null)
            //        pixelColor = solidColorBrush.Color.ToColor4();
            //}

            //ShowPositionsArray(positionsArray, pixelSize, pixelColor, model3D.Bounds.ToDXEngineBounds());
        }
Exemplo n.º 9
0
        private static WpfMeshGeometry3D PrepareMesh(XbimColour col)
        {
            var wpfMaterial = new WpfMaterial(col);

            return(new WpfMeshGeometry3D(wpfMaterial, wpfMaterial));
        }
Exemplo n.º 10
0
        /// <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);
        }