示例#1
0
        private void CreateInstances()
        {
            MeshGeometry3D meshGeometry3D;
            double         modelScaleFactor;

            if (MeshTypeComboBox.SelectedIndex == 2) // Bunnies
            {
                // Load standard Standfor Bunny model (res3) with 11533 position
                meshGeometry3D = LoadMeshFromObjFile("bun_zipper_res3.obj");

                var bounds = meshGeometry3D.Bounds;

                double diagonalSize = Math.Sqrt(bounds.SizeX * bounds.SizeX + bounds.SizeY * bounds.SizeY + bounds.SizeZ * bounds.SizeZ);
                modelScaleFactor = 20 / diagonalSize;     // Scale model so that its diagonal is 20 units big
            }
            else if (MeshTypeComboBox.SelectedIndex == 1) // Spheres
            {
                // Sphere with 382
                meshGeometry3D   = new Ab3d.Meshes.SphereMesh3D(centerPosition: new Point3D(0, 0, 0), radius: 5, segments: 20, generateTextureCoordinates: false).Geometry;
                modelScaleFactor = 1;
            }
            else
            {
                // Box with 24 positions (for each corner we need 3 positions to create sharp edges - we need 3 normal vectors for each edge)
                meshGeometry3D   = new Ab3d.Meshes.BoxMesh3D(centerPosition: new Point3D(0, 0, 0), size: new Size3D(10, 10, 10), xSegments: 1, ySegments: 1, zSegments: 1).Geometry;
                modelScaleFactor = 1;
            }

            int selectedInstancesYCount = GetSelectedInstancesYCount();


            bool  useTransparency = UseTransparencyCheckBox.IsChecked ?? false;
            float alphaColor      = useTransparency ? 0.3f : 1.0f; // When we use transparency, we set alpha color to 0.3 (we also need to set UseAlphaBlend to true - see below)

            // The following method prepare InstanceData array with data for each instance (WorldMatrix and Color)
            InstanceData[] instancedData = CreateInstancesData(new Point3D(0, 200, 0), new Size3D(400, 400, 400), (float)modelScaleFactor, 20, selectedInstancesYCount, 20, useTransparency);


            // Create InstancedGeometryVisual3D with selected meshGeometry and InstancesData
            var instancedMeshGeometryVisual3D = new InstancedMeshGeometryVisual3D(meshGeometry3D);

            instancedMeshGeometryVisual3D.InstancesData = instancedData;

            // When we use transparency, we also need to set UseAlphaBlend to true
            instancedMeshGeometryVisual3D.UseAlphaBlend = useTransparency;

            // If we would only change the InstancedData we would need to call Update method (but here this is not needed because we have set the data for the first time)
            //_instancedGeometryVisual3D.Update();


            ObjectsPlaceholder.Children.Clear();
            ObjectsPlaceholder.Children.Add(instancedMeshGeometryVisual3D);


            // Update statistics:
            //PositionsPerMeshTextBlock.Text = string.Format("Positions per mesh: {0:#,##0}", meshGeometry3D.Positions.Count);
            TotalTextBlock.Text = string.Format("Total positions: {0:#,##0} * {1:#,##0} = {2:#,##0}", meshGeometry3D.Positions.Count, 20 * 20 * selectedInstancesYCount, meshGeometry3D.Positions.Count * selectedInstancesYCount * 20 * 20);
        }
        private void CreateArrows()
        {
            if (DesignerProperties.GetIsInDesignMode(this))
            {
                return;
            }

            try
            {
                Mouse.OverrideCursor = Cursors.Hand;

                MainViewport.Children.Clear();


                var selectedArrowsNumber = GetSelectedArrowsNumber();

                _xCount = selectedArrowsNumber;
                _yCount = selectedArrowsNumber;


                var sphereVisual3D = new SphereVisual3D()
                {
                    CenterPosition = new Point3D(0, 0, 0),
                    Radius         = 10,
                    Material       = new DiffuseMaterial(Brushes.Gold)
                };

                _sphereTranslate         = new TranslateTransform3D(_sphereStartPosition.ToWpfVector3D());
                sphereVisual3D.Transform = _sphereTranslate;


                MainViewport.Children.Add(sphereVisual3D);



                _instanceData = new InstanceData[_xCount * _yCount];
                UpdateInstanceData();

                var arrowMesh3D = new Ab3d.Meshes.ArrowMesh3D(new Point3D(0, 0, 0), new Point3D(1, 0, 0), 1.0 / 15.0, 2.0 / 15.0, 45, 10, false).Geometry;

                _instancedMeshGeometryVisual3D = new InstancedMeshGeometryVisual3D(arrowMesh3D);
                _instancedMeshGeometryVisual3D.InstancesData = _instanceData;

                MainViewport.Children.Add(_instancedMeshGeometryVisual3D);


                Camera1.Refresh(); // This will regenerate camera light if it was removed with MainViewport.Children.Clear()

                TotalTextBlock.Text = string.Format(System.Globalization.CultureInfo.InvariantCulture,
                                                    "Total positions: {0:#,###}; total triangles: {1:#,###}",
                                                    _xCount * _yCount * _instancedMeshGeometryVisual3D.MeshGeometry3D.Positions.Count,
                                                    _xCount * _yCount * _instancedMeshGeometryVisual3D.MeshGeometry3D.TriangleIndices.Count / 3);
            }
            finally
            {
                Mouse.OverrideCursor = null;
            }
        }
示例#3
0
        private InstancedMeshGeometryVisual3D AddInstancedTubePath(Point3DCollection spiralPositionCollection, Color4 tubeColor)
        {
            // Setup InstanceData
            var instanceData = new InstanceData[spiralPositionCollection.Count];

            // Convert to list of Vector3
            var dxCurvePositions = spiralPositionCollection.Select(p => p.ToVector3()).ToList();


            // NOTE:
            // When a tube path is created from a lot of positions,
            // then it is worth to transform the following loop into Parallel.For loop.

            var startPosition = dxCurvePositions[0];

            for (int i = 1; i < dxCurvePositions.Count; i++)
            {
                var endPosition = dxCurvePositions[i];

                var direction = endPosition - startPosition;
                var length    = direction.Length(); // length will be used for x scale

                var scale = new Vector3(length, 1, 1);

                //direction.Normalize(); // Because we already have length, we can quickly normalize with simply dividing by length
                direction /= length;

                instanceData[i].World        = Common.MatrixUtils.GetMatrixFromNormalizedDirection(direction, startPosition, scale);
                instanceData[i].DiffuseColor = Color4.White;

                startPosition = endPosition;
            }

            // Create tube mesh with normalized radius (=1) and from (0,0,0) to (1,0,0).
            // This mesh is then transformed to connect positions along the path
            var tubeLineMesh3D = new Ab3d.Meshes.TubeLineMesh3D(startPosition: new Point3D(0, 0, 0),
                                                                endPosition: new Point3D(1, 0, 0),
                                                                radius: 1,
                                                                segments: 8,
                                                                generateTextureCoordinates: false).Geometry;

            // Create InstancedMeshGeometryVisual3D
            var instancedMeshGeometryVisual3D = new InstancedMeshGeometryVisual3D(tubeLineMesh3D);

            instancedMeshGeometryVisual3D.InstancesData = instanceData;

            // Set IsSolidColorMaterial to render tube instances with solid color without any shading based on lighting
            instancedMeshGeometryVisual3D.IsSolidColorMaterial = true;

            // Add instancedMeshGeometryVisual3D to the scene
            MainViewport.Children.Add(instancedMeshGeometryVisual3D);

            return(instancedMeshGeometryVisual3D);
        }
示例#4
0
        private void DXEngineTestingRadioButton_OnClick(object sender, RoutedEventArgs e)
        {
            _useDXEngineHitTesting = true;

            // If _instancedMeshGeometryVisual3D is null after the next frame is rendered,
            // the CreateScene method with _useDXEngineHitTesting parameter will be called.
            // This way the scene will be immediately cleared and when this will be show a new scene can be created.
            _instancedMeshGeometryVisual3D = null;

            ObjectsPlaceholder.Children.Clear();
        }
示例#5
0
        private void CreateInstancedObjects()
        {
            MainViewport.Children.Clear();


            _currentMeshType = (MeshTypes)Enum.Parse(typeof(MeshTypes), (string)ObjectsTypeComboBox.SelectedItem);
            _screenSize      = (float)ScreenSizeComboBox.SelectedItem;

            MeshGeometry3D mesh;

            switch (_currentMeshType)
            {
            case MeshTypes.Box:
                mesh = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(1, 1, 1), 1, 1, 1).Geometry;
                break;

            case MeshTypes.Sphere:
                mesh = new Ab3d.Meshes.SphereMesh3D(new Point3D(0, 0, 0), 0.5, 30).Geometry;
                break;

            case MeshTypes.Arrow:
                mesh = new Ab3d.Meshes.ArrowMesh3D(new Point3D(-0.5, 0, 0), new Point3D(0.5, 0, 0), 0.1, 0.2, 45, 30, false).Geometry;
                break;

            default:
                mesh = null;
                break;
            }

            var instancedData = GetInstancedData(_currentMeshType, _screenSize);


            _instancedMeshGeometryVisual3D = new InstancedMeshGeometryVisual3D(mesh);
            _instancedMeshGeometryVisual3D.InstancesData = instancedData;

            // To enable screen-space scaling, set the UseScreenSpaceScaling to true.
            //
            // IMPORTANT:
            // For this to work correctly, the size of the instance mesh must be 1 and the center of the mesh must be at (0, 0, 0).
            // In this case the mesh will be scaled correctly to the screen size that is defined in the instance matrix's scale component.
            _instancedMeshGeometryVisual3D.UseScreenSpaceScaling = UseScreenSpaceScaleCheckBox.IsChecked ?? false;

            MainViewport.Children.Add(_instancedMeshGeometryVisual3D);

            _instanceWorldPositions = null; // Reset array of instance positions that is used for finding the closest instance in screen coordinates
            _selectedInstanceIndex  = -1;

            // Because we have cleared all MainViewport.Children, this also removed the camera's light.
            // Call Refresh to recreate the light
            Camera1.Refresh();
        }
示例#6
0
        private void CreateInstances()
        {
            // Load standard Stanford Bunny model (res3) with 11533 position
            var meshGeometry3D = LoadMeshFromObjFile("bun_zipper_res3.obj");

            var bounds = meshGeometry3D.Bounds;

            double diagonalSize     = Math.Sqrt(bounds.SizeX * bounds.SizeX + bounds.SizeY * bounds.SizeY + bounds.SizeZ * bounds.SizeZ);
            var    modelScaleFactor = 20 / diagonalSize; // Scale model so that its diagonal is 20 units big


            // The following method prepare InstanceData array with data for each instance (WorldMatrix and Color)
            InstanceData[] instancedData = CreateInstancesData(new Point3D(0, 25, 0), new Size3D(100, 60, 100), (float)modelScaleFactor, 6, 4, 6, useTransparency: false);


            // Create InstancedGeometryVisual3D with selected meshGeometry and InstancesData
            _instancedMeshGeometryVisual3D = new InstancedMeshGeometryVisual3D(meshGeometry3D);
            _instancedMeshGeometryVisual3D.InstancesData = instancedData;

            ObjectsPlaceholder.Children.Clear();
            ObjectsPlaceholder.Children.Add(_instancedMeshGeometryVisual3D);
        }
示例#7
0
        private void CreateInstancedTubePath()
        {
            // Create curve through those points
            var controlPoints = new Point3D[]
            {
                new Point3D(-200, 50, 150),
                new Point3D(0, 50, 20),
                new Point3D(150, 50, 0),
                new Point3D(150, 50, 200),
                new Point3D(250, 50, 200)
            };

            // To create curve through specified points we must first convert the points into a bezierCurve (curve that has tangents defined for each point).
            // The curve is created with 10 points per segments - 10 points between two control points.
            var bezierCurve    = Ab3d.Utilities.BezierCurve.CreateFromCurvePositions(controlPoints);
            var curvePositions = bezierCurve.CreateBezierCurve(positionsPerSegment: 10);


            // Convert Point3D to Vector3
            var dxCurvePositions = curvePositions.Select(p => p.ToVector3()).ToList();

            // Setup InstanceData
            var instanceData = new InstanceData[curvePositions.Count];


            // NOTE:
            // When a tube path is created from a lot of positions,
            // then it is worth to transform the following loop into Parallel.For loop.

            var startPosition = dxCurvePositions[0];

            for (int i = 1; i < dxCurvePositions.Count; i++)
            {
                var endPosition = dxCurvePositions[i];

                var direction = endPosition - startPosition;
                var length    = direction.Length(); // length will be used for x scale

                var scale = new Vector3(length, 1, 1);

                //direction.Normalize(); // Because we already have length, we can quickly normalize with simply dividing by length
                direction /= length;

                instanceData[i].World        = Common.MatrixUtils.GetMatrixFromNormalizedDirection(direction, startPosition, scale);
                instanceData[i].DiffuseColor = Color4.White;

                startPosition = endPosition;
            }

            // Create tube mesh with normalized radius (=1) and from (0,0,0) to (1,0,0).
            // This mesh is then transformed to connect positions along the path
            var tubeLineMesh3D = new Ab3d.Meshes.TubeLineMesh3D(startPosition: new Point3D(0, 0, 0),
                                                                endPosition: new Point3D(1, 0, 0),
                                                                radius: 1,
                                                                segments: 8,
                                                                generateTextureCoordinates: false).Geometry;

            // Create InstancedMeshGeometryVisual3D
            var instancedMeshGeometryVisual3D = new InstancedMeshGeometryVisual3D(tubeLineMesh3D);

            instancedMeshGeometryVisual3D.InstancesData = instanceData;

            // Set IsSolidColorMaterial to render tube instances with solid color without any shading based on lighting
            instancedMeshGeometryVisual3D.IsSolidColorMaterial = true;

            // Add instancedMeshGeometryVisual3D to the scene
            MainViewport.Children.Add(instancedMeshGeometryVisual3D);
        }
        public DXEventManager3DSample()
        {
            InitializeComponent();


            Box1Visual3D.SetName("Box1Visual3D");
            BoxesGroupVisual3D.SetName("BoxesGroupVisual3D");
            Box2Visual3D.SetName("Box2Visual3D");
            Box3Visual3D.SetName("Box3Visual3D");
            Box4Visual3D.SetName("Box4Visual3D");
            Line1.SetName("Line1");
            Line2.SetName("Line2");
            Rectangle1.SetName("Rectangle1");


            var meshGeometry3D = new Ab3d.Meshes.SphereMesh3D(centerPosition: new Point3D(0, 0, 0), radius: 5, segments: 20, generateTextureCoordinates: false).Geometry;

            // The following method prepare InstanceData array with data for each instance (WorldMatrix and Color)
            InstanceData[] instancedData = DXEnginePerformance.InstancedMeshGeometry3DTest.CreateInstancesData(center: new Point3D(0, 0, 0),
                                                                                                               size: new Size3D(200, 50, 50),
                                                                                                               modelScaleFactor: 1,
                                                                                                               xCount: 10,
                                                                                                               yCount: 3,
                                                                                                               zCount: 3,
                                                                                                               useTransparency: false);


            // Create InstancedGeometryVisual3D with selected meshGeometry and InstancesData
            _instancedMeshGeometryVisual3D = new InstancedMeshGeometryVisual3D(meshGeometry3D);
            _instancedMeshGeometryVisual3D.InstancesData = instancedData;
            _instancedMeshGeometryVisual3D.SetName("InstancedMeshGeometryVisual3D");
            _instancedMeshGeometryVisual3D.Transform = new TranslateTransform3D(0, 50, 0);

            MainViewport3D.Children.Add(_instancedMeshGeometryVisual3D);

            _selectedInstanceIndex = -1;


            var model3DGroup = new Model3DGroup();

            model3DGroup.SetName("Model3DGroup");

            var frozenModel3DGroup = new Model3DGroup();

            frozenModel3DGroup.SetName("FrozenModel3DGroup");

            var box1Material = new DiffuseMaterial(Brushes.LightPink);
            var box2Material = new DiffuseMaterial(Brushes.LightCyan);

            var boxModel3D = Ab3d.Models.Model3DFactory.CreateBox(new Point3D(-100, 2, 25), new Size3D(60, 4, 50), box2Material);

            frozenModel3DGroup.Children.Add(boxModel3D);

            var pyramidModel3D = Ab3d.Models.Model3DFactory.CreatePyramid(new Point3D(-100, 2, 20), new Size3D(20, 20, 20), box2Material);

            frozenModel3DGroup.Children.Add(pyramidModel3D);

            for (int i = 0; i < 5; i++)
            {
                var geometryModel3D = new GeometryModel3D(meshGeometry3D, box1Material);
                geometryModel3D.Transform = new TranslateTransform3D(-130 + i * 15, 5, 80);
                geometryModel3D.SetName("GroupedSphere_" + i.ToString());

                model3DGroup.Children.Add(geometryModel3D);

                geometryModel3D           = new GeometryModel3D(meshGeometry3D, box2Material);
                geometryModel3D.Transform = new TranslateTransform3D(-130 + i * 15, 10, 50);
                geometryModel3D.SetName("FrozenGroupedSphere_" + i.ToString());

                frozenModel3DGroup.Children.Add(geometryModel3D);
            }


            frozenModel3DGroup.Freeze();

            MainViewport3D.Children.Add(model3DGroup.CreateModelVisual3D());
            MainViewport3D.Children.Add(frozenModel3DGroup.CreateModelVisual3D());

            _dxEventManager3D = new DXEventManager3D(MainDXViewportView);

            RegisterEventSource(Box1Visual3D);
            RegisterEventSource(BoxesGroupVisual3D);
            RegisterEventSource(Line1);
            RegisterEventSource(Line2);
            RegisterEventSource(Rectangle1);
            RegisterEventSource(_instancedMeshGeometryVisual3D);

            RegisterEventSource(model3DGroup);
            RegisterEventSource(frozenModel3DGroup);


            // Prevent TransparentPlaneVisual3D to be used by hit-testing
            _dxEventManager3D.RegisterExcludedVisual3D(TransparentPlaneVisual3D);


            this.PreviewMouseMove += delegate(object sender, MouseEventArgs args)
            {
                var position = args.GetPosition(this);
                MousePositionTextBlock.Text = $"Mouse pos: {position.X:0} {position.Y:0}";
            };

            this.PreviewMouseDown += delegate(object sender, MouseButtonEventArgs e)
            {
                var position = e.GetPosition(this);
                if (position == _lastMouseDownPosition)
                {
                    return;
                }

                System.Diagnostics.Debug.WriteLine("Mouse position: " + position.ToString());

                _lastMouseDownPosition = position;
            };


            // IMPORTANT:
            // It is very important to call Dispose method on DXSceneView after the control is not used any more (see help file for more info)
            this.Unloaded += (sender, args) => MainDXViewportView.Dispose();
        }
示例#9
0
        private void CreateScene(bool useDXEngineHitTesting)
        {
            ObjectsPlaceholder.Children.Clear();

            if (_dxEventManager3D != null)
            {
                _dxEventManager3D.ResetEventSources3D();
                _dxEventManager3D = null;
            }

            if (_wpfEventManager != null)
            {
                _wpfEventManager.ResetEventSources3D();
                _wpfEventManager = null;
            }

            if (_instancedMeshGeometryVisual3D != null)
            {
                _instancedMeshGeometryVisual3D.Dispose();
            }


            _stopwatch = new Stopwatch();
            _stopwatch.Start();

            Mouse.OverrideCursor = Cursors.Wait;


            // Create InstancedGeometryVisual3D
            _instancedMeshGeometryVisual3D = new InstancedMeshGeometryVisual3D(_instanceMeshGeometry3D);

            _instancedMeshGeometryVisual3D.InstancesData = _instancedData;


            // Setup hit testing
            if (useDXEngineHitTesting)
            {
                // Use DXEventManager3D from Ab3d.DXEngine - it has optimized hit testing for instanced objects
                _dxEventManager3D = new Ab3d.DirectX.Utilities.DXEventManager3D(MainDXViewportView);

                var visualEventSource3D = new Ab3d.DirectX.Utilities.VisualEventSource3D(_instancedMeshGeometryVisual3D);
                visualEventSource3D.MouseEnter += delegate(object sender, DirectX.Common.EventManager3D.Mouse3DEventArgs e)
                {
                    var dxRayInstancedHitTestResult = e.RayHitResult as DXRayInstancedHitTestResult;
                    if (dxRayInstancedHitTestResult != null)
                    {
                        ProcessMouseEnter(dxRayInstancedHitTestResult.HitInstanceIndex);
                    }
                };

                visualEventSource3D.MouseMove += delegate(object sender, DirectX.Common.EventManager3D.Mouse3DEventArgs e)
                {
                    var dxRayInstancedHitTestResult = e.RayHitResult as DXRayInstancedHitTestResult;
                    if (dxRayInstancedHitTestResult != null)
                    {
                        ProcessMouseMove(dxRayInstancedHitTestResult.HitInstanceIndex);
                    }
                };

                visualEventSource3D.MouseLeave += delegate(object sender, DirectX.Common.EventManager3D.Mouse3DEventArgs e)
                {
                    ProcessMouseLeave();
                };

                _dxEventManager3D.RegisterEventSource3D(visualEventSource3D);
            }
            else
            {
                //
                // IMPORTANT:
                //
                // To make WPF hit testing work (also used by EventManager3D), you need to set the IsWpfHitTestVisible to true.
                // This increases initialization time because WPF objects needs to be created for each instance, but this makes the WPF hit testing work.
                _instancedMeshGeometryVisual3D.IsWpfHitTestVisible = true;


                _wpfEventManager = new Ab3d.Utilities.EventManager3D(MainViewport);

                // Because Viewport3D is actually not shown, we need to specify different WPF's object for the source of mouse events - this could be MainDXViewportView or even better a parent Border
                _wpfEventManager.CustomEventsSourceElement = MainDXViewportView;

                var visualEventSource3D = new Ab3d.Utilities.VisualEventSource3D(_instancedMeshGeometryVisual3D);
                visualEventSource3D.MouseEnter += delegate(object sender, Mouse3DEventArgs e)
                {
                    if (e.RayHitResult == null || e.RayHitResult.ModelHit == null)
                    {
                        return; // This should not happen, but it is safer to have this check anyway
                    }
                    // Get instance index of the hit object
                    int hitInstanceIndex = GetHitInstanceIndex(e.RayHitResult);

                    ProcessMouseEnter(hitInstanceIndex);
                };

                visualEventSource3D.MouseMove += delegate(object sender, Mouse3DEventArgs e)
                {
                    if (e.RayHitResult == null || e.RayHitResult.ModelHit == null)
                    {
                        return; // This should not happen, but it is safer to have this check anyway
                    }
                    // Get instance index of the hit object
                    int hitInstanceIndex = GetHitInstanceIndex(e.RayHitResult);

                    ProcessMouseMove(hitInstanceIndex);
                };

                visualEventSource3D.MouseLeave += delegate(object sender, Mouse3DEventArgs e)
                {
                    ProcessMouseLeave();
                };

                _wpfEventManager.RegisterEventSource3D(visualEventSource3D);
            }



            ObjectsPlaceholder.Children.Add(_instancedMeshGeometryVisual3D);

            Mouse.OverrideCursor = null;

            // If we would only change the InstancedData we would need to call Update method (but here this is not needed because we have set the data for the first time)
            //_instancedGeometryVisual3D.Update();
        }
        private void CreateTestModels()
        {
            _rootModelVisual3D = new ModelVisual3D();
            MainViewport3D.Children.Add(_rootModelVisual3D);



            // SphereVisual3D
            _sphereVisual3D = new Ab3d.Visuals.SphereVisual3D()
            {
                CenterPosition = new Point3D(-50, 0, -50),
                Radius         = 30,
                Material       = new DiffuseMaterial(Brushes.Silver)
            };

            _sphereVisual3D.SetName("SphereVisual3D");

            _rootModelVisual3D.Children.Add(_sphereVisual3D);


            var readerObj   = new ReaderObj();
            var teapotModel = readerObj.ReadModel3D(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\Models\teapot-hires.obj"));

            Ab3d.Utilities.ModelUtils.CenterAndScaleModel3D(teapotModel, centerPosition: new Point3D(50, 0, -50), finalSize: new Size3D(80, 80, 80), preserveAspectRatio: true);

            _teapotModelVisual3D = new ModelVisual3D()
            {
                Content = teapotModel
            };

            teapotModel.SetName("teapot Model3D");
            _teapotModelVisual3D.SetName("teapot ModelVisual3D");

            _rootModelVisual3D.Children.Add(_teapotModelVisual3D);


            // InstancedMeshGeometryVisual3D
            var boxMesh3D = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(6, 6, 6), 1, 1, 1);

            InstanceData[] instancedData = DXEnginePerformance.InstancedMeshGeometry3DTest.CreateInstancesData(center: new Point3D(-50, 0, 50),
                                                                                                               size: new Size3D(80, 50, 80),
                                                                                                               modelScaleFactor: 1,
                                                                                                               xCount: 5,
                                                                                                               yCount: 1,
                                                                                                               zCount: 5,
                                                                                                               useTransparency: false);

            _instancedMeshGeometryVisual3D = new InstancedMeshGeometryVisual3D(boxMesh3D.Geometry);
            _instancedMeshGeometryVisual3D.InstancesData = instancedData;

            _instancedMeshGeometryVisual3D.SetName("InstancedMeshGeometryVisual3D");
            _rootModelVisual3D.Children.Add(_instancedMeshGeometryVisual3D);



            // MeshObjectNode and SceneNodeVisual3D
            var meshGeometry3D   = new Ab3d.Meshes.PyramidMesh3D(new Point3D(50, -20, 50), new Size3D(80, 40, 80)).Geometry;
            var dxMeshGeometry3D = new Ab3d.DirectX.Models.DXMeshGeometry3D(meshGeometry3D);

            var standardMaterial = new StandardMaterial()
            {
                DiffuseColor = Colors.Gold.ToColor3()
            };

            _pyramidMeshObjectNode = new Ab3d.DirectX.MeshObjectNode(dxMeshGeometry3D, standardMaterial);

            _disposables.Add(dxMeshGeometry3D);
            _disposables.Add(_pyramidMeshObjectNode);

            var sceneNodeVisual3D = new SceneNodeVisual3D(_pyramidMeshObjectNode);

            sceneNodeVisual3D.SetName("SceneNodeVisual3D");
            _rootModelVisual3D.Children.Add(sceneNodeVisual3D);
        }
        private void GenerateSampleObjects()
        {
            // We will show multiple instances of box MeshGeometry3D that is created here.
            //
            // IMPORTANT:
            //
            // It is very important to specify the correct position and size of the mesh.
            // The size should be one unit so that when you scale this mesh in instance data,
            // the scale factor will tell you the final size (for example xScale = 3 would render box with xSize set to 3).
            //
            // The position is even more important because when you will scale and rotate the mesh,
            // the mesh will be scaled and rotated around (0, 0, 0).
            // So if center of mesh is at (0, 0, 0), then the mesh will be also scale in all directions.
            // But if left edge is at (0, 0, 0), then the object will scale to the right (all coordinates are multiplied by the scale).
            //
            // What is more, the position that is at (0, 0, 0) in the original mesh will be positioned at the position
            // defined in the World transform by the M41, M42, M43 fields.
            // So if center of the mesh is at (0, 0, 0) - as in our case - then M41, M42, M43 will define the position of the center.
            // But if left-bottom-front edge would be at (0, 0, 0) - if we would use "centerPosition: new Point3D(0.5, 0.5, 0.5)" -
            // then  M41, M42, M43 will define the position of the left-bottom-front edge when the box is shown.
            //
            // See also comments in CalculateMatrixFromPositionsAndSize method.

            Point3D boxCenterPosition = CenterBoxMeshToCoordinateCenter ? new Point3D(0, 0, 0) : new Point3D(0.5, 0, 0);

            var boxMeshGeometry3D = new Ab3d.Meshes.BoxMesh3D(centerPosition: boxCenterPosition,
                                                              size: new Size3D(1, 1, 1),
                                                              xSegments: 1, ySegments: 1, zSegments: 1).Geometry;

            // Uncomment the following line to see how an ArrowMesh3D would look like (note that arrow part is also scaled so ArrowMesh3D is not a very good candidate for mesh used for instancing when scale is not uniform)
            //boxMeshGeometry3D = new Ab3d.Meshes.ArrowMesh3D(startPosition: new Point3D(0, 0, 0), endPosition: new Point3D(1, 0, 0), radius: 0.1f, arrowRadius: 0.2f, arrowAngle: 45, segments: 10, generateTextureCoordinates: false).Geometry;

            // Create an instance of InstancedMeshGeometryVisual3D
            var instancedMeshGeometryVisual3D = new InstancedMeshGeometryVisual3D(boxMeshGeometry3D);


            // Create an array of InstanceData with the matrices define in the _matrices list and Green color.

            var instanceData = new InstanceData[_samplesData.Count];

            for (int i = 0; i < _samplesData.Count; i++)
            {
                instanceData[i]            = new InstanceData(_samplesData[i].Matrix, Colors.Green.ToColor4());
                instanceData[i].World.M43 -= SamplesDistance * i;

                var wireGridVisual3D = new WireGridVisual3D()
                {
                    CenterPosition   = new Point3D(0, 0, -SamplesDistance * i),
                    Size             = new Size(4, 4),
                    WidthCellsCount  = 4,
                    HeightCellsCount = 4,
                    LineColor        = Colors.Gray,
                    LineThickness    = 1
                };

                MainViewport.Children.Add(wireGridVisual3D);


                var yAxisLineVisual3D = new LineVisual3D()
                {
                    StartPosition = wireGridVisual3D.CenterPosition,
                    EndPosition   = wireGridVisual3D.CenterPosition + new Vector3D(0, 1.2, 0),
                    LineColor     = wireGridVisual3D.LineColor,
                    LineThickness = wireGridVisual3D.LineThickness,
                    EndLineCap    = LineCap.ArrowAnchor
                };

                MainViewport.Children.Add(yAxisLineVisual3D);
            }

            instancedMeshGeometryVisual3D.InstancesData = instanceData;

            MainViewport.Children.Add(instancedMeshGeometryVisual3D);
        }