private void LoadTestModel()
        {
            // Load teapot model from obj file
            var readerObj = new Ab3d.ReaderObj();

            _teapotGeometryModel3D = readerObj.ReadModel3D(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\ObjFiles\teapot-hires.obj")) as GeometryModel3D;

            if (_teapotGeometryModel3D == null)
            {
                return;
            }

            _teapotMeshGeometry3D = (MeshGeometry3D)_teapotGeometryModel3D.Geometry;

            // Create gradient texture (128 x 1 texture with selected gradient)
            var gradientTexture = CreateGradientTexture();

            _gradientImageBrush               = new ImageBrush(gradientTexture);
            _gradientImageBrush.Viewport      = new Rect(0, 0, 1, 1);
            _gradientImageBrush.ViewportUnits = BrushMappingMode.Absolute; // Set ViewportUnits to absolute so the TextureCoordinates values are in range from 0 to 1 (defined in Viewport)

            // Set TextureCoordinates to the color for the lowest temperature - set target position far away
            UpdateTextureCoordinatesForDistance(_teapotMeshGeometry3D, targetPosition: new Point3D(10000, 0, 0), maxDistance: 50);

            _teapotGeometryModel3D.Material     = new DiffuseMaterial(_gradientImageBrush);
            _teapotGeometryModel3D.BackMaterial = new DiffuseMaterial(Brushes.Black); // Show inside of the Teapot as black

            MainViewport.Children.Add(_teapotGeometryModel3D.CreateModelVisual3D());
        }
コード例 #2
0
        private void LoadObjFile(string fileName)
        {
            var readerObj  = new Ab3d.ReaderObj();
            var wpf3DModel = readerObj.ReadModel3D(fileName);

            // To change all material to Gray use the following line:
            //Ab3d.Utilities.ModelUtils.ChangeMaterial(wpf3DModel, new DiffuseMaterial(Brushes.Gray), null);

            double readObjectSize = Math.Sqrt(wpf3DModel.Bounds.SizeX * wpf3DModel.Bounds.SizeX + wpf3DModel.Bounds.SizeY * wpf3DModel.Bounds.SizeY + wpf3DModel.Bounds.SizeZ + wpf3DModel.Bounds.SizeZ);
            var    objectsCenter  = new Point3D(wpf3DModel.Bounds.X + wpf3DModel.Bounds.SizeX / 2, wpf3DModel.Bounds.Y + wpf3DModel.Bounds.SizeY / 2, wpf3DModel.Bounds.Z + wpf3DModel.Bounds.SizeZ / 2);
            double scaleFactor    = 3.0 / readObjectSize; // Scale object to 3 meters


            var modelVisual3D = new ModelVisual3D();

            modelVisual3D.Content = wpf3DModel;

            var transform3DGroup = new Transform3DGroup();

            transform3DGroup.Children.Add(new TranslateTransform3D(-objectsCenter.X, -objectsCenter.Y, -objectsCenter.Z));
            transform3DGroup.Children.Add(new ScaleTransform3D(scaleFactor, scaleFactor, scaleFactor));
            modelVisual3D.Transform = transform3DGroup;


            MainViewport.Children.Clear();
            MainViewport.Children.Add(modelVisual3D);

            // Refresh the camea because with cleating all the objects, we have also removed the camera light.
            // Calling Refresh will recreate the light
            Camera1.Refresh();
        }
コード例 #3
0
        private void LoadObjFile(string fileName)
        {
            var readerObj = new Ab3d.ReaderObj();
            var readModel = readerObj.ReadModel3D(fileName);

            if (OptimizeReadModel)
            {
                readModel = Ab3d.Utilities.ModelOptimizer.OptimizeAll(readModel);

                readModel.Freeze();
            }

            var modelVisual3D = new ModelVisual3D();

            modelVisual3D.Content = readModel;

            MainViewport.Children.Add(modelVisual3D);


            double readObjectSize = Math.Sqrt(readModel.Bounds.SizeX * readModel.Bounds.SizeX + readModel.Bounds.SizeY * readModel.Bounds.SizeY + readModel.Bounds.SizeZ + readModel.Bounds.SizeZ);

            Camera1.Distance = readObjectSize * 1.5;

            var objectsCenter = new Point3D(readModel.Bounds.X + readModel.Bounds.SizeX / 2,
                                            readModel.Bounds.Y + readModel.Bounds.SizeY / 2,
                                            readModel.Bounds.Z + readModel.Bounds.SizeZ / 2);

            Camera1.TargetPosition = objectsCenter;
            Camera1.Heading        = 0;
        }
コード例 #4
0
        private void LoadObjFileBackgroundButton_OnClick(object sender, RoutedEventArgs e)
        {
            RootModelVisual3D.Children.Clear();
            GC.Collect();

            if (MainDXViewportView.DXScene == null)
            {
                MessageBox.Show("This sample cannot run with WPF 3D rendering");
                return;
            }

            var dxScene = MainDXViewportView.DXScene;

            Task.Factory.StartNew(() =>
            {
                var stopwatch = new Stopwatch();
                stopwatch.Start();

                // Load model from obj file
                var readerObj   = new Ab3d.ReaderObj();
                var readModel3D = readerObj.ReadModel3D(_objFileName);

                // Scale and position the read model so that its bottom center is at (0,-100,0) and it can fit into 200 x 200 x 200 Rect3D
                Ab3d.Utilities.ModelUtils.PositionAndScaleModel3D(readModel3D, new Point3D(0, -100, 0), PositionTypes.Bottom, new Size3D(200, 200, 200));
                readModel3D.Freeze();

                var createdSceneNode = Ab3d.DirectX.Models.SceneNodeFactory.CreateFromModel3D(readModel3D, null, dxScene);

                // Call InitializeResources to create all required DirectX resources from the background thread
                createdSceneNode.InitializeResources(dxScene);

                stopwatch.Stop();
                _backgroundThreadTime = (float)stopwatch.Elapsed.TotalMilliseconds;

                // Now go to UI thread and create the Visual3D objects and update the scene there.
                // There are two reasons to do that:
                // 1) We cannot create objects that are derived from Visual3D on the background thread (we also cannot freeze them with calling Freeze method - this is possible on MeshGeometry, Model3D and Material objects).
                // 2) We should not update the scene from the backgrond thread because we do not know when the UI thread is reading the scene.
                Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
                {
                    StartStopwatch();

                    // Create SceneNodeVisual3D that will show the created SceneNode
                    var sceneNodeVisual3D = new SceneNodeVisual3D(createdSceneNode);
                    RootModelVisual3D.Children.Add(sceneNodeVisual3D);

                    MainDXViewportView.Refresh(); // Manually render next frame

                    StopStopwatch(UIThreadTime2TextBlock);
                    BackgroundThreadTimeTextBlock.Text = string.Format("Background Thread time: {0:#,##0.00}ms", _backgroundThreadTime);
                }));
            });


            StartStopwatch();
            StopStopwatch(UIThreadTime2TextBlock);
        }
コード例 #5
0
        private void LoadFile(string fileName)
        {
            var readerObj = new Ab3d.ReaderObj();

            // Read the model
            var loadedModel3D = readerObj.ReadModel3D(fileName);

            Ab3d.Utilities.ModelUtils.CenterAndScaleModel3D(loadedModel3D, centerPosition: new Point3D(0, 0, 0), finalSize: new Size3D(100, 100, 100));

            MainContentVisual3D.Content = loadedModel3D;
        }
        private Model3D LoadObjFile(string fileName)
        {
            if (!System.IO.Path.IsPathRooted(fileName))
            {
                fileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
            }

            var readerObj = new Ab3d.ReaderObj();
            var readModel = readerObj.ReadModel3D(fileName);

            return(readModel);
        }
コード例 #7
0
        private void LoadModel(string fileName)
        {
            Mouse.OverrideCursor = Cursors.Wait;

            _loadedFileName = fileName;

            var readerObj = new Ab3d.ReaderObj();
            var rootModel = readerObj.ReadModel3D(fileName);

            SetModel(rootModel);

            Mouse.OverrideCursor = null;
        }
コード例 #8
0
        public BackgroundObjectsCreation()
        {
            InitializeComponent();

            _objFileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources\\Models\\dragon_vrip_res3.obj");

            // Load the test file before the actual test so that the file gets into File System cache
            var readerObj = new Ab3d.ReaderObj();

            readerObj.ReadModel3D(_objFileName);

            Camera1.StartRotation(30, 0);
        }
        public CustomAnimationSample()
        {
            InitializeComponent();

            // First load a teapot model
            string fileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources/ObjFiles/Teapot.obj");

            var readerObj   = new Ab3d.ReaderObj();
            var readModel3D = readerObj.ReadModel3D(fileName) as GeometryModel3D; // We assume that a single GeometryModel3D is returned

            if (readModel3D == null)
            {
                return;
            }


            // Set initial material - white
            double initialColorAmount = 1.0;
            byte   initialColorByte   = (byte)(initialColorAmount * 255.0);

            _initialColor = Color.FromRgb(initialColorByte, initialColorByte, initialColorByte);

            _solidColorBrush = new SolidColorBrush(_initialColor);
            var diffuseMaterial = new DiffuseMaterial(_solidColorBrush);

            readModel3D.Material = diffuseMaterial;


            // Show teapot model
            var modelVisual3D = readModel3D.CreateModelVisual3D();

            MainViewport.Children.Add(modelVisual3D);


            // Create a custom SolidColorBrushAnimationNode (defined below)
            _solidColorBrushAnimationNode = new SolidColorBrushAnimationNode(_solidColorBrush);
            _solidColorBrushAnimationNode.ColorAmountTrack.Keys.Add(new DoubleKeyFrame(frameNumber: 0, doubleValue: initialColorAmount));
            _solidColorBrushAnimationNode.ColorAmountTrack.Keys.Add(new DoubleKeyFrame(frameNumber: 100, doubleValue: 0.0));                // quickly (1s) animate to 0 (black)
            _solidColorBrushAnimationNode.ColorAmountTrack.Keys.Add(new DoubleKeyFrame(frameNumber: 400, doubleValue: initialColorAmount)); // slowly (3s) animate back to initial value (white)

            _solidColorBrushAnimationNode.ColorAmountTrack.SetEasingFunctionToAllKeys(Ab3d.Animation.EasingFunctions.QuadraticEaseInOutFunction);


            _animationController = new AnimationController();
            _animationController.FramesPerSecond = 100;
            _animationController.AutoRepeat      = true;
            _animationController.AutoReverse     = false;

            _animationController.AnimationNodes.Add(_solidColorBrushAnimationNode);
        }
コード例 #10
0
        private MeshGeometry3D LoadMeshFromObjFile(string fileName)
        {
            if (!System.IO.Path.IsPathRooted(fileName))
            {
                fileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources\\Models\\" + fileName);
            }

            var readerObj   = new Ab3d.ReaderObj();
            var readModel3D = readerObj.ReadModel3D(fileName) as GeometryModel3D;

            if (readModel3D == null)
            {
                return(null);
            }

            return(readModel3D.Geometry as MeshGeometry3D);
        }
コード例 #11
0
        private void CreateScene()
        {
            var dummyModel = new Model3DGroup();

            // Let's say that we do not know the size and position of the loaded model3D.
            //
            // If we just want to show the model, the it is recommended to adjust the camera position and distance.
            // In case of using TargetPositionCamera we can use the following code to do that:

            // var model3DBounds = model3D.Bounds; // Get local accessor to avoid multiple call to DependencyProperty getters

            // double modelSize = Math.Sqrt(model3DBounds.SizeX * model3DBounds.SizeX + model3DBounds.SizeY * model3DBounds.SizeY + model3DBounds.SizeZ + model3DBounds.SizeZ);

            // var modelCenter = new Point3D(model3DBounds.X + model3DBounds.SizeX / 2,
            //                               model3DBounds.Y + model3DBounds.SizeY / 2,
            //                               model3DBounds.Z + model3DBounds.SizeZ / 2);

            // Camera1.Distance = modelSize * 2;
            // Camera1.TargetPosition = modelCenter;


            // But if you want to add the model to existing 3D objects,
            // then we need to adjust the position and size of the read model.
            //
            // The easiest way to do that is to use PositionAndScaleModel3D method from Ab3d.Utilities.ModelUtils class:
            Ab3d.Utilities.ModelUtils.PositionAndScaleModel3D(dummyModel, position: new Point3D(0, 0, 0), positionType: PositionTypes.Bottom, finalSize: new Size3D(100, 100, 100), preserveAspectRatio: true);

            // If you want to center the model, you can also use the CenterAndScaleModel3D method:
            Ab3d.Utilities.ModelUtils.CenterAndScaleModel3D(dummyModel, centerPosition: new Point3D(0, 0, 0), finalSize: new Size3D(100, 100, 100), preserveAspectRatio: true);

            // If you only need to position or scale the mode, then you can also use CenterModel3D or ScaleModel3D methods:
            Ab3d.Utilities.ModelUtils.CenterModel3D(dummyModel, centerPosition: new Point3D(0, 0, 0));
            Ab3d.Utilities.ModelUtils.ScaleModel3D(dummyModel, finalSize: new Size3D(100, 100, 100));


            // Load dragon model and show it with 3 different positions and scales
            string fileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources\\ObjFiles\\dragon_vrip_res3.obj");

            var readerObj = new Ab3d.ReaderObj();
            var model3D   = readerObj.ReadModel3D(fileName);

            AddModel(model3D, new Point3D(-100, 0, 0), PositionTypes.Bottom, new Size3D(80, 80, 80));
            AddModel(model3D, new Point3D(-40, 60, 0), PositionTypes.Left | PositionTypes.Top, new Size3D(80, 60, 80));
            AddModel(model3D, new Point3D(100, 15, 0), PositionTypes.Center, new Size3D(80, 30, 60), preserveAspectRatio: false);
        }
コード例 #12
0
        private void LoadObjFileUIButton_OnClick(object sender, RoutedEventArgs e)
        {
            RootModelVisual3D.Children.Clear();
            StartStopwatch();

            // Load model from obj file
            var readerObj   = new Ab3d.ReaderObj();
            var readModel3D = readerObj.ReadModel3D(_objFileName);

            // Scale and position the read model so that its bottom center is at (0,-100,0) and it can fit into 200 x 200 x 200 Rect3D
            Ab3d.Utilities.ModelUtils.PositionAndScaleModel3D(readModel3D, new Point3D(0, -100, 0), PositionTypes.Bottom, new Size3D(200, 200, 200));
            readModel3D.Freeze();

            // Create ModelVisual3D from readModel3D and add it to the scene
            RootModelVisual3D.Children.Add(readModel3D.CreateModelVisual3D());

            MainDXViewportView.Refresh(); // Manually render next frame

            StopStopwatch(UIThreadTime1TextBlock);
        }
コード例 #13
0
        private void CreateTestScene()
        {
            MainViewport.Children.Clear();

            string fileName = AppDomain.CurrentDomain.BaseDirectory + @"Resources\ObjFiles\house with trees.obj";

            var readerObj    = new Ab3d.ReaderObj();
            var sceneModel3D = readerObj.ReadModel3D(fileName);

            LogMessage("Loaded:\r\n" + Ab3d.Utilities.Dumper.GetObjectHierarchyString(sceneModel3D));

            Ab3d.Utilities.ModelUtils.CenterAndScaleModel3D(sceneModel3D,
                                                            centerPosition: new Point3D(0, 0, 0),
                                                            finalSize: new Size3D(100, 100, 100),
                                                            preserveAspectRatio: true);

            _sceneVisual3D         = new ModelVisual3D();
            _sceneVisual3D.Content = sceneModel3D;
            _sceneVisual3D.SetName("SceneVisual3D"); // Set Name dependency properties so that we can read then when getting hit test result

            MainViewport.Children.Add(_sceneVisual3D);


            _glassPlaneVisual3D = new Ab3d.Visuals.PlaneVisual3D()
            {
                CenterPosition  = new Point3D(0, 0, 45),
                Size            = new Size(70, 10),
                Normal          = new Vector3D(0, 0, 1),
                HeightDirection = new Vector3D(0, 1, 0),
                Material        = new DiffuseMaterial(new SolidColorBrush(Color.FromArgb(100, 200, 200, 255)))
            };

            _glassPlaneVisual3D.BackMaterial = _glassPlaneVisual3D.Material;
            _glassPlaneVisual3D.SetName("GlassPlaneVisual3D");

            MainViewport.Children.Add(_glassPlaneVisual3D);


            Camera1.Refresh(); // This will recreate camera's light that was removed when we called MainViewport.Children.Clear()
        }
コード例 #14
0
        private void AddCustomRenderedObjects()
        {
            var readerObj             = new Ab3d.ReaderObj();
            var originalDragonModel3D = readerObj.ReadModel3D(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\Models\dragon_vrip_res3.obj")) as GeometryModel3D;

            if (originalDragonModel3D == null)
            {
                return;
            }


            var meshGeometry3D = (MeshGeometry3D)originalDragonModel3D.Geometry;

            // Update positions in MeshGeometry3D to a desired size
            var transformedMeshGeometry3D = Ab3d.Utilities.MeshUtils.PositionAndScaleMeshGeometry3D(meshGeometry3D,
                                                                                                    position: new Point3D(0, 0, 0),
                                                                                                    positionType: PositionTypes.Bottom,
                                                                                                    finalSize: new Size3D(50, 50, 50),
                                                                                                    preserveAspectRatio: true,
                                                                                                    transformNormals: true);

            var backgroundDragonModel3D = new GeometryModel3D(transformedMeshGeometry3D, new DiffuseMaterial(Brushes.Blue));

            backgroundDragonModel3D.Transform = new TranslateTransform3D(-30, 0, 0);

            // We could also use:
            //var backgroundDragonModel3D = originalDragonModel3D.Clone();
            //Ab3d.Utilities.ModelUtils.ChangeMaterial(backgroundDragonModel3D, newMaterial: new DiffuseMaterial(Brushes.Blue), newBackMaterial: null);
            //Ab3d.Utilities.TransformationsHelper.AddTransformation(backgroundDragonModel3D, new TranslateTransform3D(-30, 0, 0));

            AddBackgroundObject(backgroundDragonModel3D);


            var overlayDragonModel3D = new GeometryModel3D(transformedMeshGeometry3D, new DiffuseMaterial(Brushes.Red));

            overlayDragonModel3D.Transform = new TranslateTransform3D(30, 0, 0);

            AddOverlayObject(overlayDragonModel3D);
        }
コード例 #15
0
        private void LoadFromResource(string resourceName)
        {
            var    objImporter    = new Ab3d.ReaderObj();
            Stream resourceStream = GetResourceStream(resourceName);

            try
            {
                // Read 3D models from obj file into wpf3DModel
                // We also use GetResourceStream method to allow reading any additional resources (.mtf file with definition for materials and texture image files)
                var wpf3DModel = objImporter.ReadModel3D(resourceStream, GetResourceStream);

                // Show the model
                ContentVisual.Content = wpf3DModel;

                // Refresh the SceneCamera to measure the scene again and adjust itself accordingly
                Camera1.Refresh();
            }
            catch (Exception ex)
            {
                MessageBox.Show("ERROR:\r\n" + ex.Message);
            }
        }
コード例 #16
0
        private void CreateScene()
        {
            // IMPORTANT:
            // Before the Form is closed, we need to dispose all the DXEngine objects that we created (all that implement IDisposable).
            // This means that all materials, Mesh objects and SceneNodes need to be disposed.
            // To make this easier, we can use the DisposeList collection that will hold IDisposable objects.
            _disposables = new DisposeList();


            var readerObj   = new Ab3d.ReaderObj();
            var readModel3D = readerObj.ReadModel3D(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\Models\dragon_vrip_res3.obj")) as GeometryModel3D;

            if (readModel3D == null)
            {
                return;
            }

            _meshGeometry3D = (MeshGeometry3D)readModel3D.Geometry;

            _originalMeshGeometryBounds = _meshGeometry3D.Bounds;

            // We need to make sure that we have normals defined
            if (_meshGeometry3D.Normals == null || _meshGeometry3D.Normals.Count == 0)
            {
                _meshGeometry3D.Normals = Ab3d.Utilities.MeshUtils.CalculateNormals(_meshGeometry3D);
            }


            if (UseSimpleMeshRadioButton.IsChecked ?? false)
            {
                AddSimpleMesh();
            }
            else
            {
                AddMeshGeometry3D();
            }
        }
        private void CreateScene()
        {
            // Load sample model
            var readerObj        = new Ab3d.ReaderObj();
            var rootModel3DGroup = readerObj.ReadModel3D("pack://application:,,,/Ab3d.PowerToys.Samples;component/Resources/ObjFiles/robotarm.obj") as Model3DGroup;

            _initialPosition = rootModel3DGroup.Bounds.GetCenterPosition();

            RootModelVisual3D.Content = rootModel3DGroup;

            _transform3DGroup = new Transform3DGroup();

            _xAxisAngleRotation3D = new AxisAngleRotation3D(new Vector3D(1, 0, 0), 0);
            _yAxisAngleRotation3D = new AxisAngleRotation3D(new Vector3D(0, 1, 0), 0);
            _zAxisAngleRotation3D = new AxisAngleRotation3D(new Vector3D(0, 0, 1), 0);
            _translateTransform3D = new TranslateTransform3D();

            _transform3DGroup.Children.Add(new RotateTransform3D(_xAxisAngleRotation3D));
            _transform3DGroup.Children.Add(new RotateTransform3D(_yAxisAngleRotation3D));
            _transform3DGroup.Children.Add(new RotateTransform3D(_zAxisAngleRotation3D));
            _transform3DGroup.Children.Add(_translateTransform3D);

            RootModelVisual3D.Transform = _transform3DGroup;
        }
コード例 #18
0
        private void CreateCustomScene()
        {
            var blueMaterial = new DiffuseMaterial(Brushes.Blue);


            var sphereVisual3D = new SphereVisual3D();

            sphereVisual3D.CenterPosition = new Point3D(200, 20, -80);
            sphereVisual3D.Radius         = 20;
            sphereVisual3D.Material       = blueMaterial;

            MainDXViewportView.Viewport3D.Children.Add(sphereVisual3D);


            var grayCylinder = new CylinderVisual3D();

            grayCylinder.BottomCenterPosition = new Point3D(200, 0, 100);
            grayCylinder.Radius   = 20;
            grayCylinder.Height   = 100;
            grayCylinder.Material = new DiffuseMaterial(Brushes.LightGray);

            MainDXViewportView.Viewport3D.Children.Add(grayCylinder);


            for (int x = -300; x < 500; x += 100)
            {
                var yellowBox = new BoxVisual3D();
                yellowBox.CenterPosition = new Point3D(x, 30, 0);
                yellowBox.Size           = new Size3D(20, 60, 20);
                yellowBox.Material       = new DiffuseMaterial(Brushes.Yellow);

                MainDXViewportView.Viewport3D.Children.Add(yellowBox);
            }


            var readerObj = new Ab3d.ReaderObj();

            _teapotModel = readerObj.ReadModel3D(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\Models\Teapot.obj"));

            var transform3DGroup = new Transform3DGroup();

            transform3DGroup.Children.Add(new ScaleTransform3D(3, 3, 3));
            transform3DGroup.Children.Add(new TranslateTransform3D(-100, -20, 200));
            _teapotModel.Transform = transform3DGroup;

            var teapotVisual3D = new ModelVisual3D();

            teapotVisual3D.Content = _teapotModel;

            MainDXViewportView.Viewport3D.Children.Add(teapotVisual3D);


            var imageBrush = new ImageBrush();

            imageBrush.ImageSource = new BitmapImage(new Uri(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources/GrassTexture.jpg")));
            var grassMaterial = new DiffuseMaterial(imageBrush);

            _greenBox3D = new BoxVisual3D();
            _greenBox3D.CenterPosition = new Point3D(0, -2, 0);
            _greenBox3D.Size           = new Size3D(SceneSize, 4, SceneSize);
            _greenBox3D.Material       = grassMaterial;

            MainDXViewportView.Viewport3D.Children.Add(_greenBox3D);
        }
コード例 #19
0
        private void CreateRootModel()
        {
            switch (ObjectComboBox.SelectedIndex)
            {
            case 0:
                Ab3d.Meshes.BoxMesh3D box = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(130, 60, 100), 1, 1, 1);
                _rootMesh = box.Geometry;
                break;

            case 1:
                Ab3d.Meshes.BoxMesh3D box2 = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(130, 60, 100), 4, 4, 4);
                _rootMesh = box2.Geometry;
                break;

            case 2:
                Ab3d.Meshes.SphereMesh3D sphere = new Ab3d.Meshes.SphereMesh3D(new Point3D(0, 0, 0), 80, 10);
                _rootMesh = sphere.Geometry;
                break;

            case 3:
                Ab3d.Meshes.SphereMesh3D sphere2 = new Ab3d.Meshes.SphereMesh3D(new Point3D(0, 0, 0), 80, 5);
                _rootMesh = sphere2.Geometry;
                break;

            case 4:
                Ab3d.Meshes.CylinderMesh3D cylinder = new Ab3d.Meshes.CylinderMesh3D(new Point3D(0, -50, 0), 60, 100, 12, true);
                _rootMesh = cylinder.Geometry;
                break;

            case 5:
                Ab3d.Meshes.ConeMesh3D cone = new Ab3d.Meshes.ConeMesh3D(new Point3D(0, -50, 0), 30, 60, 100, 12, true);
                _rootMesh = cone.Geometry;
                break;

            case 6:
                Ab3d.Meshes.ConeMesh3D cone2 = new Ab3d.Meshes.ConeMesh3D(new Point3D(0, -50, 0), 30, 60, 100, 6, false);
                _rootMesh = cone2.Geometry;
                break;

            case 7:
                var readerObj   = new Ab3d.ReaderObj();
                var teapotModel = readerObj.ReadModel3D(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\ObjFiles\Teapot.obj")) as GeometryModel3D;

                if (teapotModel == null)
                {
                    return;
                }

                // Get the teapot MeshGeometry3D
                _rootMesh = (MeshGeometry3D)teapotModel.Geometry;

                break;

            default:
                _rootMesh = null;
                break;
            }


            var geometryModel3D = new GeometryModel3D(_rootMesh, new DiffuseMaterial(Brushes.Silver));

            MainViewport.Children.Clear();
            MainViewport.Children.Add(geometryModel3D.CreateModelVisual3D());

            MeshInspector.MeshGeometry3D = _rootMesh;
        }
コード例 #20
0
        private void CreateScene(Viewport3D parentViewport3D, double sphereRadius, double depthBias, TargetPositionCamera targetPositionCamera, bool showSphere)
        {
            parentViewport3D.Children.Clear();

            if (showSphere)
            {
                var sphereVisual3D = new Ab3d.Visuals.SphereVisual3D()
                {
                    CenterPosition          = new Point3D(0, 0, 0),
                    Radius                  = sphereRadius,
                    Segments                = 10,
                    Material                = new DiffuseMaterial(Brushes.SkyBlue),
                    UseCachedMeshGeometry3D = false // This will create a new MeshGeometry3D and will not use the shared MeshGeometry3D with radius = 1
                };

                parentViewport3D.Children.Add(sphereVisual3D);


                var sphereMesh = ((GeometryModel3D)sphereVisual3D.Content).Geometry as MeshGeometry3D;

                var sphereLinePositions = CollectWireframeLinePositions(sphereMesh);

                var multiLineVisual3D = new Ab3d.Visuals.MultiLineVisual3D()
                {
                    Positions     = sphereLinePositions,
                    LineThickness = 0.5,
                    LineColor     = Colors.Black
                };

                // To specify line depth bias to the Ab3d.PowerToys line Visual3D objects,
                // we use SetDXAttribute extension method and use LineDepthBias as DXAttributeType
                // NOTE: This can be used only before the Visual3D is created by DXEngine.
                // If you want to change the line bias after the object has been rendered, use the SetDepthBias method (defined below)
                multiLineVisual3D.SetDXAttribute(DXAttributeType.LineDepthBias, depthBias);

                // It would be also possible to set the depth with changing the DepthBias on the WpfWireframeVisual3DNode.
                // This is done with using the SetDepthBias method
                //SetDepthBias(dxViewportView, wireframeVisual3D, depthBias);


                parentViewport3D.Children.Add(multiLineVisual3D);

                _shownLineVisual3D = multiLineVisual3D;
            }
            else
            {
                if (_sampleModel == null)
                {
                    var readerObj = new Ab3d.ReaderObj();
                    _sampleModel = readerObj.ReadModel3D(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\Models\Teapot.obj"), null, new DiffuseMaterial(Brushes.SkyBlue));

                    _sampleModel.Freeze();
                }

                double readObjectRadius = Math.Sqrt(_sampleModel.Bounds.SizeX * _sampleModel.Bounds.SizeX + _sampleModel.Bounds.SizeZ + _sampleModel.Bounds.SizeZ) / 2;
                double scaleFactor      = sphereRadius / readObjectRadius;

                var finalModel = new Model3DGroup();
                finalModel.Children.Add(_sampleModel);
                finalModel.Transform = new ScaleTransform3D(scaleFactor, scaleFactor, scaleFactor);
                finalModel.Freeze();

                var wireframeVisual3D = new WireframeVisual3D()
                {
                    OriginalModel = finalModel,
                    WireframeType = WireframeVisual3D.WireframeTypes.WireframeWithOriginalSolidModel,
                    UseModelColor = false,
                    LineColor     = Colors.Black,
                    LineThickness = 0.5
                };

                // To specify line depth bias to the WireframeVisual3D,
                // we use SetDXAttribute extension method and use LineDepthBias as DXAttributeType
                wireframeVisual3D.SetDXAttribute(DXAttributeType.LineDepthBias, depthBias);

                // It would be also possible to set the depth with changing the DepthBias on the WpfWireframeVisual3DNode.
                // This is done with using the SetDepthBias method
                //SetDepthBias(dxViewportView, wireframeVisual3D, depthBias);


                parentViewport3D.Children.Add(wireframeVisual3D);

                _shownLineVisual3D = wireframeVisual3D;
            }

            _previousCameraDistance       = sphereRadius * 4;
            targetPositionCamera.Distance = _previousCameraDistance;
            targetPositionCamera.Offset   = new Vector3D(0, sphereRadius * 0.4, 0);
        }
コード例 #21
0
        private void CreateSceneObjects()
        {
            // NOTE: For VR all units must be in meters

            var rootVisual3D = new ModelVisual3D();

            // NOTE that the size of the scene will affect the quality of the shadows (bigger scene requite bigger shadow map)
            var floorBox = new BoxVisual3D()
            {
                CenterPosition = new Point3D(0, -0.5, 0),
                Size           = new Size3D(10, 1, 10),        // 10 x 1 x 10 meters
                Material       = new DiffuseMaterial(Brushes.Green)
            };

            rootVisual3D.Children.Add(floorBox);

            double centerX      = 0;
            double centerZ      = 0;
            double circleRadius = 3;
            double boxesHeight  = 1.3;

            var grayMaterial = new DiffuseMaterial(Brushes.Gray);
            var goldMaterial = new MaterialGroup();

            goldMaterial.Children.Add(new DiffuseMaterial(Brushes.Gold));
            goldMaterial.Children.Add(new SpecularMaterial(Brushes.White, 16));

            // Create spheres on top of boxes that are organized in a circle
            for (int a = 0; a < 360; a += 36)
            {
                double rad = SharpDX.MathUtil.DegreesToRadians(a + 18);
                double x   = Math.Sin(rad) * circleRadius + centerX;
                double z   = Math.Cos(rad) * circleRadius + centerZ;

                var boxVisual3D = new BoxVisual3D()
                {
                    CenterPosition = new Point3D(x, boxesHeight * 0.5, z),
                    Size           = new Size3D(0.2, boxesHeight, 0.2),
                    Material       = grayMaterial
                };

                var sphereVisual3D = new SphereVisual3D()
                {
                    CenterPosition = new Point3D(x, boxesHeight + 0.1, z),
                    Radius         = 0.1,
                    Material       = goldMaterial
                };

                rootVisual3D.Children.Add(boxVisual3D);
                rootVisual3D.Children.Add(sphereVisual3D);
            }


            // Read dragon model from obj file into Model3D object
            string dragonFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\dragon_vrip_res3.obj");

            var readerObj     = new Ab3d.ReaderObj();
            var dragonModel3D = readerObj.ReadModel3D(dragonFileName);

            // Scale the model
            dragonModel3D.Transform = new ScaleTransform3D(10, 10, 10);

            Ab3d.Utilities.ModelUtils.ChangeMaterial(dragonModel3D, newMaterial: goldMaterial, newBackMaterial: null);

            // Add it to the scene
            var modelVisual3D = new ModelVisual3D();

            modelVisual3D.Content = dragonModel3D;

            rootVisual3D.Children.Add(modelVisual3D);


            // Add another box that will represet a base for the dragon model
            var dragonBaseBox = new BoxVisual3D()
            {
                CenterPosition = new Point3D(0, 0.27, 0),
                Size           = new Size3D(2.2, 0.54, 1),
                Material       = grayMaterial
            };

            rootVisual3D.Children.Add(dragonBaseBox);

            _viewport3D.Children.Clear();
            _viewport3D.Children.Add(rootVisual3D);
        }
コード例 #22
0
        private void CreateScene()
        {
            // IMPORTANT:
            // Before the Form is closed, we need to dispose all the DXEngine objects that we created (all that implement IDisposable).
            // This means that all materials, Mesh objects and SceneNodes need to be disposed.
            // To make this easier, we can use the DisposeList collection that will hold IDisposable objects.
            _disposables = new DisposeList();


            //
            // 1)
            //
            // The easiest way to add 3D models to DXEngine's scene is to add WPF's Visual3D objects to Viewport3D.Children collection:

            var pyramidVisual3D = new Ab3d.Visuals.PyramidVisual3D()
            {
                BottomCenterPosition = new Point3D(-100, 0, 0),
                Size     = new Size3D(80, 50, 80),
                Material = new DiffuseMaterial(Brushes.Blue)
            };

            pyramidVisual3D.SetName("PyramidVisual3D");

            MainViewport.Children.Add(pyramidVisual3D);


            // We could also start from PyramidMesh3D and then create GeometryModel3D and ModelVisual3D
            //var pyramidMeshGeometry3D = new Ab3d.Meshes.PyramidMesh3D(new Point3D(100, 0, 0), new Size3D(80, 50, 80)).Geometry;

            //if (pyramidMeshGeometry3D.Normals.Count == 0)
            //    pyramidMeshGeometry3D.Normals = Ab3d.Utilities.MeshUtils.CalculateNormals(pyramidMeshGeometry3D);

            //var geometryModel3D = new GeometryModel3D(pyramidMeshGeometry3D, diffuseMaterial);
            //var modelVisual3D = new ModelVisual3D()
            //{
            //    Content = geometryModel3D
            //};

            //MainViewport.Children.Add(modelVisual3D);



            // DXEngine internally converts WPF objects into SceneNodes.
            // You can get the string that describes the SceneNodes with opening Visual Studio Immediate Window and execting the following:
            // MainDXViewportView.DXScene.DumpSceneNodes();
            //
            // Usually this is the best was to define the 3D scene.
            //
            // But if you have very complex objects with a lot of positions, it might be good to create the SceneNodes manually.
            // This allows faster initialization because WPF 3D objects are not created.
            // Also all the memory used by WPF 3D objects can be freed.
            //
            // Because WPF uses double type for Point3D and Vector3D types instead of float as in DirectX and DXEngine,
            // the memory size required for a 3D objects in WPF is almost twice the size of what is required in DXEngine.
            //
            // For example if your object has 100.000 positions, the the memory requirements are the following:
            //
            // In WPF:
            // Positions:           100.000 * 3 (x,y,z) * 8 (8 bytes for one double value) = 2.400.000 bytes
            // Normals:             100.000 * 3 (x,y,z) * 8 (8 bytes for one double value) = 2.400.000 bytes
            // Texture coordinates: 100.000 * 2 (u,y) * 8 (8 bytes for one double value)   = 1.600.000 bytes
            // Triangle indices:    100.000 * 4 (4 bytes for one Int32)                    =   400.000 bytes (the actual number of triangle indices may be different - depends on how many positions are shared between triangles)
            // TOTAL:                                                                      = 6.800.000 bytes = 6.7 MB
            //
            // In DXEngine:
            // Positions:           100.000 * 3 (x,y,z) * 4 (4 bytes for one float value) = 1.200.000 bytes
            // Normals:             100.000 * 3 (x,y,z) * 4 (4 bytes for one float value) = 1.200.000 bytes
            // Texture coordinates: 100.000 * 2 (u,y) * 4 (4 bytes for one float value)   =   800.000 bytes
            // Triangle indices:    100.000 * 4 (4 bytes for one Int32)                   =   400.000 bytes
            // TOTAL:                                                                     = 3.600.000 bytes = 3.5 MB
            //
            // Usually both objects need to be initialized (takes CPU time) and are stored in memory.
            //
            //
            // When the DXEngine's SceneNodes are manually created, the WPF objects can be cleared from memory
            // or event the SceneNodes can be created without the intermediate WPF objects.
            //
            // One the SceneNode is created it can be added to the scene with using SceneNodeVisual3D.
            // This is a Visual3D and can be added to the Viewport3D.Children collection.
            // The object also provides a way to add Transformation to the SceneNode.
            //
            // A disadvantage of creating SceneNodes is that such objects cannot be shown when WPF 3D rendering is used (for example in case when DXEngine falls back to WPF 3D rendering because of problems with DirectX initialization).
            // Another disadvantage is that it is more complicated to create and modify SceneNodes.
            //
            // Usually, when memory usage is not problematic, it is better to use standard WPF 3D objects.

            //
            // 2)
            //
            // Create MeshObjectNode from GeometryMesh with providing arrays (IList<T>) for positions, normals, textureCoordinates and triangleIndices:

            Vector3[] positions;
            Vector3[] normals;
            Vector2[] textureCoordinates;
            int[]     triangleIndices;

            // Get Pyramid mesh data
            GetObjectDataArrays(out positions, out normals, out textureCoordinates, out triangleIndices);


            // The easiest way to create DXEngine's material is to use Ab3d.DirectX.Materials.WpfMaterial that takes a WPF material and converts it into DXEngine's material
            var diffuseMaterial = new DiffuseMaterial(Brushes.Green);
            var dxMaterial      = new Ab3d.DirectX.Materials.WpfMaterial(diffuseMaterial);

            _disposables.Add(dxMaterial);

            // Create SceneNode
            // First create GeometryMesh object from the mesh arrays
            var geometryMesh = new Ab3d.DirectX.GeometryMesh(positions, normals, textureCoordinates, triangleIndices, "PyramidMesh3D");

            _disposables.Add(geometryMesh);

            // NOTE:
            // We could also create GeometryMesh from WPF's MeshGeometry with help from DXMeshGeometry3D:
            //var wpfPyramidMesh = new Meshes.PyramidMesh3D(bottomCenterPosition: new System.Windows.Media.Media3D.Point3D(0, 0, 0),
            //                                              size: new System.Windows.Media.Media3D.Size3D(30, 20, 10));

            //var geometryMesh = new Ab3d.DirectX.Models.DXMeshGeometry3D(wpfPyramidMesh.Geometry, "PyramidMesh");


            // Use GeometryMesh to create MeshObjectNode (SceneNode from GeometryMesh object)
            var meshObjectNode = new Ab3d.DirectX.MeshObjectNode(geometryMesh, dxMaterial);

            meshObjectNode.Name = "Green-MeshObjectNode-from-GeometryMesh";

            _disposables.Add(meshObjectNode);

            // Use SceneNodeVisual3D to show SceneNode in DXViewportView
            var sceneNodeVisual3D = new SceneNodeVisual3D(meshObjectNode);

            //sceneNodeVisual3D.Transform = new TranslateTransform3D(0, 0, 0);

            MainViewport.Children.Add(sceneNodeVisual3D);


            //
            // 3)
            //
            // Create MeshObjectNode from SimpleMesh<T> with providing VertexBufferArray and IndexBufferArray:
            // This option provides faster initialization, because the VertexBufferArray is already generated and it can be directly used to create DirectX vertex buffer.
            // In the previous sample the VertexBufferArray was generated in the GeometryMesh from positions, normals, textureCoordinates arrays.
            //
            // If you can store your 3D models in disk (or some other location) in a form of VertexBuffer and IndexBuffer,
            // then this is the fastes way to initialize 3D objects.

            //
            // 3a)
            //
            // The standard way to create a SimpleMesh is to use the PositionNormalTexture or some other struct that defines the data for one array:

            PositionNormalTexture[] vertexBuffer;
            int[] indexBuffer;
            GetVertexAndIndexBuffer(out vertexBuffer, out indexBuffer);

            var simpleMesh = new SimpleMesh <PositionNormalTexture>(vertexBuffer,
                                                                    indexBuffer,
                                                                    inputLayoutType: InputLayoutType.Position | InputLayoutType.Normal | InputLayoutType.TextureCoordinate,
                                                                    name: "SimpleMesh-from-PositionNormalTexture-array");

            _disposables.Add(simpleMesh);

            diffuseMaterial = new DiffuseMaterial(Brushes.Red);
            dxMaterial      = new Ab3d.DirectX.Materials.WpfMaterial(diffuseMaterial);

            _disposables.Add(dxMaterial);

            _redPyramidObjectNode      = new Ab3d.DirectX.MeshObjectNode(simpleMesh, dxMaterial);
            _redPyramidObjectNode.Name = "Red-MeshObjectNode-from-SimpleMesh";

            _disposables.Add(_redPyramidObjectNode);

            sceneNodeVisual3D           = new SceneNodeVisual3D(_redPyramidObjectNode);
            sceneNodeVisual3D.Transform = new TranslateTransform3D(100, 0, 0);

            MainViewport.Children.Add(sceneNodeVisual3D);



            //
            // 3b)
            //
            // It is also possible to create SimpleMesh with a base type - for example float (for example if we read data from file).
            // In this case we need to set the ArrayStride property.
            //
            // A drawback of using a non-standard vertex buffer (Vector3, PositionNormalTexture, PositionNormal or PositionTexture)
            // is that such mesh does not support hit testing.
            // In this sample this is demonstrated with camera rotation around mouse hit object - it is not possible to rotate around SimpleMesh<float>.

            float[] floatVertexBuffer;
            GetFloatVertexAndIndexBuffer(out floatVertexBuffer, out indexBuffer);

            var floatSimpleMesh = new SimpleMesh <float>(floatVertexBuffer,
                                                         indexBuffer,
                                                         inputLayoutType: InputLayoutType.Position | InputLayoutType.Normal | InputLayoutType.TextureCoordinate,
                                                         name: "SimpleMesh-from-float-array");

            _disposables.Add(floatSimpleMesh);

            // IMPORTANT:
            // When we do not use PositionNormalTexture or PositionNormal, the DXEngine cannot calculate Bounds of the SimpleMesh for us.
            // In this case we need to calculate and specify Bounds manually:
            // Defined bounds for the following mesh: new Ab3d.Meshes.PyramidMesh3D(new Point3D(0, 0, 0), new Size3D(80, 50, 80))
            floatSimpleMesh.Bounds = new Bounds(new BoundingBox(minimum: new Vector3(-40, -25, -40), maximum: new Vector3(40, 25, 40)));

            // Because we created SimpleMesh with a base type (float),
            // we need to specify how many array elements define one Vertex.
            // This is 8 in our case: 3 (position x,y,z) + 3 (normal x,y,z) + 2 (texture coordinate u,v) = 8
            floatSimpleMesh.ArrayStride = 8;


            diffuseMaterial = new DiffuseMaterial(Brushes.Orange);
            dxMaterial      = new Ab3d.DirectX.Materials.WpfMaterial(diffuseMaterial);

            _disposables.Add(dxMaterial);

            _orangePyramidObjectNode      = new Ab3d.DirectX.MeshObjectNode(floatSimpleMesh, dxMaterial);
            _orangePyramidObjectNode.Name = "Orange-MeshObjectNode-from-FloatSimpleMesh";

            _disposables.Add(_orangePyramidObjectNode);

            sceneNodeVisual3D           = new SceneNodeVisual3D(_orangePyramidObjectNode);
            sceneNodeVisual3D.Transform = new TranslateTransform3D(200, 0, 0);

            MainViewport.Children.Add(sceneNodeVisual3D);



            //
            // 3c)
            //
            // Instead of float array elements, it is also possible to use byte array to create SimpleMesh.
            //
            // As before, a drawback of using a non-standard vertex buffer (Vector3, PositionNormalTexture, PositionNormal or PositionTexture)
            // is that such mesh does not support hit testing.
            // In this sample this is demonstrated with camera rotation around mouse hit object - it is not possible to rotate around SimpleMesh<float>.

            byte[] byteVertexBuffer;
            GetByteVertexAndIndexBuffer(out byteVertexBuffer, out indexBuffer);

            var byteSimpleMesh = new SimpleMesh <byte>(byteVertexBuffer,
                                                       indexBuffer,
                                                       inputLayoutType: InputLayoutType.Position | InputLayoutType.Normal | InputLayoutType.TextureCoordinate,
                                                       name: "SimpleMesh-from-byte-array");

            _disposables.Add(byteSimpleMesh);

            // IMPORTANT:
            // When we do not use PositionNormalTexture or PositionNormal, the DXEngine cannot calculate Bounds of the SimpleMesh for us.
            // In this case we need to calculate and specify Bounds manually:
            // Defined bounds for the following mesh: new Ab3d.Meshes.PyramidMesh3D(new Point3D(0, 0, 0), new Size3D(80, 50, 80))
            byteSimpleMesh.Bounds = new Bounds(new BoundingBox(minimum: new Vector3(-40, -25, -40), maximum: new Vector3(40, 25, 40)));

            // Because we created SimpleMesh with a base type (byte),
            // we need to specify how many array elements define one Vertex.
            // This is 32 in our case: 8 (8x float value) * 4 (4 bytes for one float) = 32
            byteSimpleMesh.ArrayStride = 32;


            diffuseMaterial = new DiffuseMaterial(Brushes.Yellow);
            dxMaterial      = new Ab3d.DirectX.Materials.WpfMaterial(diffuseMaterial);

            _disposables.Add(dxMaterial);

            meshObjectNode      = new Ab3d.DirectX.MeshObjectNode(byteSimpleMesh, dxMaterial);
            meshObjectNode.Name = "Yellow-MeshObjectNode-from-ByteSimpleMesh";

            _disposables.Add(meshObjectNode);

            sceneNodeVisual3D           = new SceneNodeVisual3D(meshObjectNode);
            sceneNodeVisual3D.Transform = new TranslateTransform3D(300, 0, 0);

            MainViewport.Children.Add(sceneNodeVisual3D);


            //
            // 4)
            //
            // When a frozen Model3DGroup is added to the DXViewportView, it is converted into the WpfOptimizedModel3DGroupNode (derived from SceneNode).
            // In this case both WPF and DXEngine's 3D objects data are stored in memory.
            //
            // To release the WPF 3D objects data, it is possible to create the WpfOptimizedModel3DGroupNode manually and
            // then clear the used WPF 3D objects.
            // This can be done with setting the AutomaticallyClearWpfObjectsAfterInitialization property on WpfOptimizedModel3DGroupNode to true,
            // or by calling the ClearWpfObjects method on WpfOptimizedModel3DGroupNode.

            string dragonModelFileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources\\Models\\dragon_vrip_res3.obj");

            var     readerObj   = new Ab3d.ReaderObj();
            Model3D readModel3D = readerObj.ReadModel3D(dragonModelFileName);

            double scale = 100 / readModel3D.Bounds.SizeX; // Scale the model to 100 SizeX

            readModel3D.Transform = new ScaleTransform3D(scale, scale, scale);

            var model3DGroup = readModel3D as Model3DGroup;

            if (model3DGroup == null)
            {
                model3DGroup = new Model3DGroup();
                model3DGroup.Children.Add(readModel3D);
            }

            model3DGroup.Freeze();


            var wpfOptimizedModel3DGroupNode = new Ab3d.DirectX.Models.WpfOptimizedModel3DGroupNode(model3DGroup, name: "Frozen Model3DGroup");

            wpfOptimizedModel3DGroupNode.AutomaticallyClearWpfObjectsAfterInitialization = true; // This will clear the WPF 3D models that are referenced by WpfOptimizedModel3DGroupNode when the DirectX objects are created

            _disposables.Add(wpfOptimizedModel3DGroupNode);

            sceneNodeVisual3D           = new SceneNodeVisual3D(wpfOptimizedModel3DGroupNode);
            sceneNodeVisual3D.Transform = new TranslateTransform3D(-100, -20, -100);

            MainViewport.Children.Add(sceneNodeVisual3D);


            //
            // 5)
            //
            // The following code shows how to load texture with using TextureLoader

            if (MainDXViewportView.DXScene != null)
            {
                var planeGeometry3D  = new Ab3d.Meshes.PlaneMesh3D(new Point3D(0, 0, 0), new Vector3D(0, 1, 0), new Vector3D(1, 0, 0), new Size(80, 80), 1, 1).Geometry;
                var dxMeshGeometry3D = new DXMeshGeometry3D(planeGeometry3D);
                _disposables.Add(dxMeshGeometry3D);

                // Load texture file into ShaderResourceView (in our case we load dds file; but we could also load png file)
                string textureFileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources/ab4d-logo-220x220.dds");


                // The easiest way to load image file and in the same time create a material with the loaded texture is to use the CreateStandardTextureMaterial method.
                var standardMaterial = Ab3d.DirectX.TextureLoader.CreateStandardTextureMaterial(MainDXViewportView.DXScene.DXDevice, textureFileName);

                // We need to manually dispose the created StandardMaterial and ShaderResourceView
                _disposables.Add(standardMaterial);
                _disposables.Add(standardMaterial.DiffuseTextures[0]);


                // If we want more control over the material creation process, we can use the following code:

                //// To load a texture from file, you can use the TextureLoader.LoadShaderResourceView (this supports loading standard image files and also loading dds files).
                //// This method returns a ShaderResourceView and it can also set a textureInfo parameter that defines some of the properties of the loaded texture (bitmap size, dpi, format, hasTransparency).
                //TextureInfo textureInfo;
                //var loadedShaderResourceView = Ab3d.DirectX.TextureLoader.LoadShaderResourceView(MainDXViewportView.DXScene.Device,
                //                                                                                 textureFileName,
                //                                                                                 out textureInfo);
                //_disposables.Add(loadedShaderResourceView);

                //// Get recommended BlendState based on HasTransparency and HasPreMultipliedAlpha values.
                //// Possible values are: CommonStates.Opaque, CommonStates.PremultipliedAlphaBlend or CommonStates.NonPremultipliedAlphaBlend.
                //var recommendedBlendState = MainDXViewportView.DXScene.DXDevice.CommonStates.GetRecommendedBlendState(textureInfo.HasTransparency, textureInfo.HasPremultipliedAlpha);

                //// Now we can create a DXEngine's StandardMaterial
                //var standardMaterial = new StandardMaterial()
                //{
                //    // Set ShaderResourceView into array of diffuse textures
                //    DiffuseTextures = new ShaderResourceView[] {loadedShaderResourceView},
                //    TextureBlendState = recommendedBlendState,

                //    HasTransparency = textureInfo.HasTransparency,

                //    // When showing texture, the DiffuseColor represents a color mask - each color from texture is multiplied with DiffuseColor (White preserves the original color)
                //    DiffuseColor = Colors.White.ToColor3()
                //};

                //_disposables.Add(standardMaterial);


                meshObjectNode      = new Ab3d.DirectX.MeshObjectNode(dxMeshGeometry3D, standardMaterial);
                meshObjectNode.Name = "MeshObjectNode-from-PlaneMesh3D";

                _disposables.Add(meshObjectNode);

                sceneNodeVisual3D           = new SceneNodeVisual3D(meshObjectNode);
                sceneNodeVisual3D.Transform = new TranslateTransform3D(0, 0, 100);

                MainViewport.Children.Add(sceneNodeVisual3D);
            }



            // Add PointLight
            var pointLight = new PointLight(Colors.White, new Point3D(100, 500, 0));

            MainViewport.Children.Add(pointLight.CreateModelVisual3D());

            Camera1.ShowCameraLight = ShowCameraLightType.Never;
        }
コード例 #23
0
        private void CreateTeapotWireframeModel(Point3D centerPosition, Size3D size, DiffuseMaterial material)
        {
            // The most common way to show wireframe models in DXEngine is to use WireframeVisual3D from Ab3d.PowerToys - see commented code below:
            //var wireframeVisual3D = new WireframeVisual3D()
            //{
            //    WireframeType = WireframeVisual3D.WireframeTypes.WireframeWithOriginalSolidModel,
            //    UseModelColor = false,
            //    LineThickness = 1,
            //    LineColor = Colors.Yellow,
            //    Transform = new TranslateTransform3D(0, 0, -50)
            //};
            //
            //wireframeVisual3D.OriginalModel = teapotModel;
            //// Set LineDepthBias to prevent rendering wireframe at the same depth as the 3D objects.
            //// This creates much nicer 3D lines. See the LineDepthBiasSample for more information.
            //wireframeVisual3D.SetDXAttribute(DXAttributeType.LineDepthBias, 0.1);

            // But in this sample we show special line rendering.
            // Therefore we will create standard WPF GeometryModel3D and then apply LineMaterial to it so the model will be rendered with wireframe lines

            // First read teapot model from Teapot.obj file
            var readerObj   = new Ab3d.ReaderObj();
            var teapotModel = readerObj.ReadModel3D(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\Models\Teapot.obj")) as GeometryModel3D;

            if (teapotModel == null)
            {
                return;
            }

            // Get the teapot MeshGeometry3D
            var meshGeometry3D = (MeshGeometry3D)teapotModel.Geometry;


            // Get transformation to scale and position the model to the centerPosition and size
            var bounds = meshGeometry3D.Bounds;

            double scaleX = size.X / bounds.SizeX;
            double scaleY = size.Y / bounds.SizeY;
            double scaleZ = size.Z / bounds.SizeZ;

            double minScale = Math.Min(scaleX, Math.Min(scaleY, scaleZ));

            scaleX = scaleY = scaleZ = minScale;

            var scaleTransform3D = new ScaleTransform3D(scaleX, scaleY, scaleZ);

            bounds = scaleTransform3D.TransformBounds(bounds);


            double cx = bounds.X + bounds.SizeX * 0.5;
            double cy = bounds.Y + bounds.SizeY * 0.5;
            double cz = bounds.Z + bounds.SizeZ * 0.5;

            var translateTransform3D = new TranslateTransform3D(centerPosition.X - cx, centerPosition.Y - cy, centerPosition.Z - cz);

            var transform3DGroup = new Transform3DGroup();

            transform3DGroup.Children.Add(scaleTransform3D);
            transform3DGroup.Children.Add(translateTransform3D);



            // First create the standard solid model with the specified material
            var geometryModel3D = new GeometryModel3D(meshGeometry3D, material);

            geometryModel3D.Transform = transform3DGroup;

            var modelVisual3D = new ModelVisual3D()
            {
                Content = geometryModel3D
            };

            TestObjectsModelVisual3D.Children.Add(modelVisual3D);


            // To render wireframe object, we first create a DXEngine material that is used to rendered lines or wireframe
            if (_dxLineMaterial == null)
            {
                _dxLineMaterial = new LineMaterial()
                {
                    LineThickness = 1,
                    LineColor     = Colors.Yellow.ToColor4(),
                    DepthBias     = 0.1f
                                    // Set DepthBias to prevent rendering wireframe at the same depth as the 3D objects. This creates much nicer 3D lines because lines are rendered on top of 3D object and not in the same position as 3D object.
                };
            }
            else
            {
                _dxLineMaterial.ReadZBuffer = true;
            }

            // Now create standard WPF material and assign DXEngine's LineMaterial to it.
            // This will use the dxLineMaterial when the wpfLineMaterial will be rendered in DXEngine
            var wpfWireframeMaterial = new DiffuseMaterial(Brushes.Red);

            wpfWireframeMaterial.SetUsedDXMaterial(_dxLineMaterial);


            // Finally, create another GeometryModel3D, but this time we will use DXEngine's LineMaterial to render it
            _wireframeGeometryModel3D           = new GeometryModel3D(meshGeometry3D, wpfWireframeMaterial);
            _wireframeGeometryModel3D.Transform = transform3DGroup;

            modelVisual3D = new ModelVisual3D()
            {
                Content = _wireframeGeometryModel3D
            };

            TestObjectsModelVisual3D.Children.Add(modelVisual3D);
        }
コード例 #24
0
        private void LoadFile(string fileName)
        {
            var readerObj = new Ab3d.ReaderObj();

            // Read the model
            _originalModel3D = readerObj.ReadModel3D(fileName);

            if (_originalModel3D == null)
            {
                InfoTextBox.Text = "Cannot read " + fileName;
                return;
            }

            // Optimize the model with ModelOptimizer
            // This will combine meshes that have the same material
            // Check the Ab3d.PowerToys help file for more details about ModelOptimizer
            var modelOptimizer = new Ab3d.Utilities.ModelOptimizer()
            {
                // Use default settings - set there only for your information
                CompareMaterialsByHash = true,

                // CompareMaterialsByHash specifies how the materials are compared
                // If true, the the actual material data are compared, if false than materials are compared by reference
                CombineModelsWithSameMaterial = true,

                // Note that this will prevent any furher changes of the model (but on the other hand this would allow to read the model on another thread)
                FreezeAll = true
            };

            // Optimize
            _optimizedModel3D = modelOptimizer.Optimize(_originalModel3D);



            // Update the camera for new model
            Point3D center;
            double  size;

            GetModelCenterAndSize(_originalModel3D, out center, out size);

            if (double.IsNaN(center.X))
            {
                center = new Point3D(); // 0, 0, 0
            }
            if (double.IsInfinity(size))
            {
                size = 1;
            }

            Camera1.Distance       = size * 1.2;
            Camera1.CameraWidth    = size * 1.2; // In case we have OrthographicCamera we also set the CameraWidth
            Camera1.TargetPosition = center;


            // Show the model - start with optimized model
            ContentVisual3D.Content = _optimizedModel3D;


            // Update statistics (show differences between original and optimized model)
            string modelStatistics = GetModelStatistics();

            InfoTextBox.Text = string.Format("Opened file: {0}\r\n\r\n{1}\r\n\r\n{2}", System.IO.Path.GetFileName(fileName), modelStatistics, InfoTextBox.Text);
        }
コード例 #25
0
        private void LoadObj(string fileName)
        {
            if (_isLoading)
            {
                return;
            }

            bool isNewFile = (_fileName != fileName);

            _fileName   = fileName;
            _wpf3DModel = null;


            // Set ReadPolygonIndices in UI thread
            // When true ReaderObj will read PolygonIndices collection that can be used to show polygons instead of triangles
            _readerObj.ReadPolygonIndices = ReadPolygonIndicesCheckBox.IsChecked ?? false;

            // To read polygon indices from the read models,
            // iterating through GeometryModel3D objects (children of Model3DGroup) and
            // then converting its Geometry object into MeshGeometry3D.
            // The MeshGeometry3D defines the Positions, TriangleIndices, Normals and TextureCoordinates collections.
            //
            // On top of that the Ab3d.PowerToys and ReaderObj can also add the polygon indices collection.
            // It is set to MeshGeometry3D as a PolygonIndices dependency property (defined in Ab3d.Utilities.MeshUtils).
            // You can read the PolygonIndices directly with the following:
            //
            // var polygonIndices = meshGeometry3D.GetValue(Ab3d.Utilities.MeshUtils.PolygonIndicesProperty) as Int32Collection;
            //
            // You can also use the GetPolygonIndices, SetPolygonIndices and GetPolygonPositions extension methods on MeshGeometry3D,
            // or use GetPolygonPositions from MeshUtils.
            //
            // See also the following to get know how the polygon positions are organized:
            // https://www.ab4d.com/help/PowerToys/html/F_Ab3d_Utilities_MeshUtils_PolygonIndicesProperty.htm



            // UH: The following code is much much easier with async and await from .net 4.5
            // But here we want to use only .net 4.0

            // Read obj file and convert to wpf 3d objects in background thread
            var readObjFileTask = new Task(() =>
            {
                _lastException = null;

                try
                {
                    string texturesPath = Path.GetDirectoryName(_fileName);

                    // Read obj file from _fileName
                    // We read the object names into objectNames dictionary (Dictionary<string, Model3D>)
                    // This allows us to quickly get objects from their name.
                    // ReaderObj also set name to all objects and materials with using SetName extension method
                    // This way you can get object name or material name with GetName method.
                    // For example:
                    // _wpf3DModel.GetName();

                    var defaultMaterial = new DiffuseMaterial(Brushes.Silver);

                    _wpf3DModel = _readerObj.ReadModel3D(_fileName, texturesPath, defaultMaterial);

                    if (_wpf3DModel != null)
                    {
                        // We need to freeze the model because it was created on another thread.
                        // After the model is forzen, it cannot be changed any more.
                        // if you want to change the model, than Convert method must be called on UI thread
                        // or you must clone the read object in the UI thread
                        _wpf3DModel.Freeze();
                    }

                    // NOTE:
                    // If we wanted more control over reading obj files, we could read them in two steps
                    // 1) Read obj file into ObjFileData object
                    // 2) Convert read ObjFileData object into WPF Model3D
                    // The following code does that (uncomment it to see it in action):

                    //var objFileData = _readerObj.ReadFile(_fileName);
                    ////var objFileData = _readerObj.ReadStream(fileStream);

                    //var objMeshToWpfModel3DConverter = new ObjFileToWpfModel3DConverter();
                    //objMeshToWpfModel3DConverter.InvertYTextureCoordinate = false;
                    //objMeshToWpfModel3DConverter.TexturesDirectory = Path.GetDirectoryName(_fileName);

                    //// DefaultMaterial is a Material that is used when no other material is specified.
                    //// Actually with leaving DefaultMaterial as null, the same Silver material would be used (setting it here only to show the user what properties exist)
                    //objMeshToWpfModel3DConverter.DefaultMaterial = new DiffuseMaterial(Brushes.Silver);

                    //// ReuseMaterials specified if one material instance defined in obj file can be reused for all Model3D objects that use that material.
                    //// If false than a new material instance will be created for each usage
                    //// This is useful when user wants to change material on individual objects without applying the change to all other objects that use that material.
                    //// Default value is true.
                    //objMeshToWpfModel3DConverter.ReuseMaterials = true;

                    //_wpf3DModel = _objMeshToWpfModel3DConverter.Convert(objFileData);
                }
                catch (Exception ex)
                {
                    _lastException = ex;
                }
            });

            // After reading the obj file and converting it to WPF 3D objects we need to show the objects or errors - this needs to be done on UI thread
            var showObjectTask = readObjFileTask.ContinueWith(_ =>
            {
                try
                {
                    if (_lastException != null)
                    {
                        ResultTextBlock.Text = "ERROR reading obj file:\r\n" + _lastException.Message;
                    }
                    else if (_wpf3DModel != null)
                    {
                        string objectsDescriptions = Ab3d.Utilities.Dumper.GetObjectHierarchyString(_wpf3DModel);

                        if (_readerObj.Errors != null && _readerObj.Errors.Count > 0)
                        {
                            var sb = new StringBuilder();

                            sb.AppendLine("Obj file errors:");
                            foreach (var error in _readerObj.Errors)
                            {
                                sb.AppendLine(error);
                            }

                            ResultTextBlock.Text = objectsDescriptions + Environment.NewLine + Environment.NewLine + sb.ToString();
                        }
                        else
                        {
                            ResultTextBlock.Text = objectsDescriptions;
                        }

                        //ResultTextBlock.Text = Ab3d.Utilities.Dumper.GetMeshInitializationCode(model);
                        //ResultTextBlock.Text += "\r\n\n" + Ab3d.Utilities.Dumper.Dump(model);

                        ContentVisual.Content = _wpf3DModel;

                        // NOTE:
                        // We could show both solid model and wireframe in WireframeVisual3D (ContentWireframeVisual) with using WireframeWithOriginalSolidModel for WireframeType.
                        // But in this sample we show solid frame is separate ModelVisual3D and therefore we show only wireframe in WireframeVisual3D.
                        ContentWireframeVisual.BeginInit();
                        ContentWireframeVisual.ShowPolygonLines = ReadPolygonIndicesCheckBox.IsChecked ?? false;
                        ContentWireframeVisual.OriginalModel    = _wpf3DModel;
                        ContentWireframeVisual.EndInit();



                        // Calculate the center of the model and its size
                        // This will be used to position the camera

                        if (isNewFile) // If we just reloaded the previous file, we preserve the current camera TargetPosition and Distance
                        {
                            var bounds = _wpf3DModel.Bounds;

                            var modelCenter = new Point3D(bounds.X + bounds.SizeX / 2,
                                                          bounds.Y + bounds.SizeY / 2,
                                                          bounds.Z + bounds.SizeZ / 2);

                            var modelSize = Math.Sqrt(bounds.SizeX * bounds.SizeX +
                                                      bounds.SizeY * bounds.SizeY +
                                                      bounds.SizeZ * bounds.SizeZ);


                            Camera1.TargetPosition = modelCenter;
                            Camera1.Distance       = modelSize * 1.5;
                        }

                        // If the read model already define some lights, then do not show the Camera's light
                        if (ModelUtils.HasAnyLight(_wpf3DModel))
                        {
                            Camera1.ShowCameraLight = ShowCameraLightType.Never;
                        }
                        else
                        {
                            Camera1.ShowCameraLight = ShowCameraLightType.Always;
                        }
                    }

                    _isLoading = false;
                }
                finally
                {
                    Mouse.OverrideCursor = null;
                }
            },
                                                              TaskScheduler.FromCurrentSynchronizationContext()); // Run on UI thread


            _isLoading           = true;
            Mouse.OverrideCursor = Cursors.Wait;

            // Start tasks
            readObjFileTask.Start();
        }
コード例 #26
0
        private void CreateScene()
        {
            if (MainDXViewportView.DXScene == null)
            {
                return; // Not yet initialized or using WPF 3D
            }
            Mouse.OverrideCursor = Cursors.Wait;

            MainViewport.Children.Clear();
            _disposables.Dispose();           // Dispose previously used resources

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


            float pixelSize = (float)PixelSizeComboBox.SelectedItem;

            switch (SceneTypeComboBox.SelectedIndex)
            {
            case 0:     // Box
                var boxModel3D = Ab3d.Models.Model3DFactory.CreateBox(new Point3D(0, 0, 0), new Size3D(100, 100, 100), 10, 10, 10, new DiffuseMaterial(Brushes.Green));
                ShowGeometryModel3D(boxModel3D, pixelSize);
                break;

            case 1:     // Sphere
                var sphereModel3D = Ab3d.Models.Model3DFactory.CreateSphere(new Point3D(0, 0, 0), 80, 50, new DiffuseMaterial(Brushes.DeepSkyBlue));
                ShowGeometryModel3D(sphereModel3D, pixelSize);
                break;

            case 2:     // Dragon model
                var readerObj   = new Ab3d.ReaderObj();
                var readModel3D = readerObj.ReadModel3D(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\Models\dragon_vrip_res3.obj")) as GeometryModel3D;

                var transform3DGroup = new Transform3DGroup();
                transform3DGroup.Children.Add(new ScaleTransform3D(1000, 1000, 1000));
                transform3DGroup.Children.Add(new TranslateTransform3D(0, -120, 0));

                readModel3D.Transform = transform3DGroup;

                // This will be available in the next version of Ab3d.PowerToys
                //Ab3d.Utilities.ModelUtils.CenterAndScaleModel3D(readModel3D, new Point3D(-200, 0, 0), new Size3D(200, 200, 200), preserveAspectRatio: true, preserveCurrentTransformation: true);

                Ab3d.Utilities.ModelUtils.ChangeMaterial(readModel3D, newMaterial: new DiffuseMaterial(Brushes.Gold), newBackMaterial: null);

                ShowGeometryModel3D(readModel3D, pixelSize);
                break;

            case 3:     // 10,000 pixels (100 x 1 x 100)
                var positionsArray001 = CreatePositionsArray(new Point3D(0, 0, 0), new Size3D(300, 1, 300), 100, 1, 100);
                ShowPositionsArray(positionsArray001, pixelSize, Colors.Red.ToColor4(), new Point3D(0, 0, 0), new Size3D(300, 1, 300));
                break;

            case 4:     // 1 million pixels (100 x 100 x 100)
                var positionsArray1 = CreatePositionsArray(new Point3D(0, 0, 0), new Size3D(220, 220, 220), 100, 100, 100);
                ShowPositionsArray(positionsArray1, pixelSize, Colors.Red.ToColor4(), new Point3D(0, 0, 0), new Size3D(220, 220, 220));
                break;

            case 5:     // 9 million pixels (9 x 1M)
                AddMillionBlocks(3, 3, new Size3D(80, 80, 80), pixelSize, Colors.Red.ToColor4());
                break;

            case 6:     // 25 million pixels (5 x 5 x 1M)
                AddMillionBlocks(5, 5, new Size3D(60, 60, 60), pixelSize, Colors.Red.ToColor4());
                break;

            case 7:     // 100 million pixels (10 x 10 x 1M)
                AddMillionBlocks(10, 10, new Size3D(30, 30, 30), pixelSize, Colors.Red.ToColor4());
                break;
            }

            Mouse.OverrideCursor = null;
        }
コード例 #27
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();
        }
コード例 #28
0
        public ExtensionMethods()
        {
            InitializeComponent();


            var point1  = new Point3D(10, 10, 10);
            var vector1 = point1.ToVector3D();

            var vector2 = new Vector3D(10, 10, 10);
            var point2  = vector2.ToPoint3D();


            var sphereMesh    = new Ab3d.Meshes.SphereMesh3D(new Point3D(0, 0, 0), 10, 30).Geometry;
            var sphereModel3D = new GeometryModel3D(sphereMesh, new DiffuseMaterial(Brushes.Gold));

            var sphereModelVisual = sphereModel3D.CreateModelVisual3D();


            Point3D centerPosition = sphereModel3D.Bounds.GetCenterPosition();



            // Load sample model
            var readerObj        = new Ab3d.ReaderObj();
            var rootModel3DGroup = readerObj.ReadModel3D("pack://application:,,,/Ab3d.PowerToys.Samples;component/Resources/ObjFiles/robotarm.obj") as Model3DGroup;



            Viewport3D MainViewport3D = new Viewport3D();

            MainViewport3D.Name = "MainViewport3D";
            MainViewport3D.Children.Add(rootModel3DGroup.CreateModelVisual3D());


            var redDiffuseMaterial = new DiffuseMaterial(Brushes.Red);

            MainViewport3D.Children.ForEachGeometryModel3D((geometryModel3D) =>
            {
                // This code is called for every GeometryModel3D inside rootModel3DGroup
                geometryModel3D.Material = redDiffuseMaterial;
            });



            int totalPositions = 0;

            rootModel3DGroup.ForEachGeometryModel3D((geometryModel3D) =>
            {
                // This code is called for every GeometryModel3D inside rootModel3DGroup
                var meshGeometry3D = geometryModel3D.Geometry as MeshGeometry3D;
                if (meshGeometry3D != null && meshGeometry3D.Positions != null)
                {
                    totalPositions += meshGeometry3D.Positions.Count;
                }
            });


            MainViewport3D.Children.ForEachVisual3D((modelVisual3D) =>
            {
                // This code is called for every ModelVisual3D in MainViewport3D
                var sphereVisual3D = modelVisual3D as Ab3d.Visuals.SphereVisual3D;
                if (sphereVisual3D != null)
                {
                    sphereVisual3D.Radius *= 1.2;
                }
            });



            var allPositions = new List <Point3D>();

            Ab3d.Utilities.ModelIterator.IterateGeometryModel3DObjects(model3D : rootModel3DGroup,
                                                                       parentTransform3D : null,
                                                                       callback : delegate(GeometryModel3D geometryModel3D, Transform3D transform3D)
            {
                // This code is called for every GeometryModel3D inside rootModel3DGroup
                // transform3D is set to the Transform3D with all parent transformations or to null if there is no parent transformation
                var meshGeometry3D = geometryModel3D.Geometry as MeshGeometry3D;

                if (meshGeometry3D != null)
                {
                    var positions = meshGeometry3D.Positions;
                    if (positions != null)
                    {
                        int positionsCount = positions.Count;
                        for (var i = 0; i < positionsCount; i++)
                        {
                            Point3D onePosition = positions[i];

                            if (transform3D != null)
                            {
                                onePosition = transform3D.Transform(positions[i]);
                            }

                            allPositions.Add(onePosition);
                        }
                    }
                }
            });


            // MainViewport3D.DumpHierarchy()
            DumpHierarchyTextBlock.Text = Ab3d.Utilities.Dumper.GetObjectHierarchyString(MainViewport3D);



            // Most extension methods are meant to be used in Visual Studio Immediate Window
            // For example: geometryModel3D.Dump();
            // This writes detailed information about geometryModel3D into the Immediate Window (using Console.Write)
            // For this sample, we do not want to display info text into Colose.Write, but instead show the text in the UI
            // To do this we use GetDumpString and other methods that are also used by the Dump extension.

            // Same as: rootModel3DGroup.Dump()
            string model3DGroupDumpString = Ab3d.Utilities.Dumper.GetDumpString(rootModel3DGroup);

            var baseMotorGeometryModel3D = readerObj.NamedObjects["BaseMotor"] as GeometryModel3D;
            // Same as: geometryModel3D.Dump();
            string geometryModel3DDumpString = Ab3d.Utilities.Dumper.GetDumpString(baseMotorGeometryModel3D);

            // Same as geometryModel3D.Geometry.Dump(5, "0.0")
            // Max 6 lines of data
            // "0.0" is format string
            string geometryDumpString = Ab3d.Utilities.Dumper.GetDumpString(baseMotorGeometryModel3D.Geometry, 6, "0.0");


            // Create a custom specular material
            var materialGroup = new MaterialGroup();

            materialGroup.Children.Add(new DiffuseMaterial(Brushes.Gold));
            materialGroup.Children.Add(new SpecularMaterial(Brushes.White, 16));

            // Same as: materialGroup.Dump();
            string materialDump = Ab3d.Utilities.Dumper.GetDumpString(materialGroup);


            var axisAngleRotation3D = new AxisAngleRotation3D(new Vector3D(0, 1, 0), 30);
            var rotateTransform3D   = new RotateTransform3D(axisAngleRotation3D, 100, 200, 300);

            var transform3DGroup = new Transform3DGroup();

            transform3DGroup.Children.Add(new ScaleTransform3D(1.0, 2.0, 0.5));
            transform3DGroup.Children.Add(rotateTransform3D);

            // Same as: transform3DGroup.Value.Dump();
            string matrixDump = Ab3d.Utilities.Dumper.GetMatrix3DText(transform3DGroup.Value);

            // Same as: transform3DGroup.Value.Dump(5);
            string matrix5Dump = Ab3d.Utilities.Dumper.GetMatrix3DText(transform3DGroup.Value, numberOfDecimals: 5);

            // Same as: transform3DGroup.Dump();
            string transformDump = Ab3d.Utilities.Dumper.GetTransformText(transform3DGroup);

            // Same as: rootModel3DGroup.Bounds.Dump();
            string boundDump = Ab3d.Utilities.Dumper.GetBoundsText(rootModel3DGroup.Bounds);

            string meshInitializationText = Ab3d.Utilities.Dumper.GetMeshInitializationCode(baseMotorGeometryModel3D.Geometry);


            ModelGroupDumpTextBlock.Text     = model3DGroupDumpString;
            GeometryModelDumpTextBlock.Text  = geometryModel3DDumpString;
            MeshGeometryDumpTextBlock.Text   = geometryDumpString;
            MaterialDumpTextBlock.Text       = materialDump;
            MatrixDumpTextBlock.Text         = matrixDump;
            MatrixDump5TextBlock.Text        = matrix5Dump;
            TransformDumpTextBlock.Text      = transformDump;
            BoundsTextBlock.Text             = boundDump;
            MeshInitializationTextBlock.Text = meshInitializationText;
        }
コード例 #29
0
        private void CreateRootModel()
        {
            bool show3DLine = false;

            switch (ObjectComboBox.SelectedIndex)
            {
            case 0:
                Ab3d.Meshes.SphereMesh3D sphere = new Ab3d.Meshes.SphereMesh3D(new Point3D(0, 0, 0), 80, 10);
                _rootMesh = sphere.Geometry;
                break;

            case 1:
                Ab3d.Meshes.SphereMesh3D sphere2 = new Ab3d.Meshes.SphereMesh3D(new Point3D(0, 0, 0), 80, 5);
                _rootMesh = sphere2.Geometry;
                break;

            case 2:
                // NOTE: Here we create an optimized version of sphere but it does not have texture coordinates
                // If we do not need texture coordinates (do not need to show texture), than we can slightly simplify the sphere model.
                // When we also need to create texture coordinates, the top most position that represent the same point in space is defined multiple times
                // - each time with slightly different texture coordinate (so that the whole top line on the texture is shown around the top sphere position).
                // Also there are x + 1 position around the sphere (in one row) - one additional position is added that the first and last position in the "row" are in the same space position,
                // but the first position has x texture coordinate 0, the last position has x texture coordinate 1 - this shows the whole texture nicely around the sphere.
                // If texture coordinates are not needed, than we do not need to define more than one upper and bottom positions,
                // and also do not need to add another position to the row.
                // Optimized sphere can be created only with SphereMesh3D object (not with SphereVisual3D)
                Ab3d.Meshes.SphereMesh3D sphere3 = new Ab3d.Meshes.SphereMesh3D(new Point3D(0, 0, 0), 80, 12, false);     // false: generateTextureCoordinates
                _rootMesh = sphere3.Geometry;
                break;

            case 3:
                Ab3d.Meshes.BoxMesh3D box = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(130, 60, 100), 1, 1, 1);
                _rootMesh = box.Geometry;
                break;

            case 4:
                Ab3d.Meshes.BoxMesh3D box2 = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(130, 60, 100), 4, 4, 4);
                _rootMesh = box2.Geometry;
                break;

            case 5:
                Ab3d.Meshes.CylinderMesh3D cylinder = new Ab3d.Meshes.CylinderMesh3D(new Point3D(0, -50, 0), 60, 100, 12, true);
                _rootMesh = cylinder.Geometry;
                break;

            case 6:
                Ab3d.Meshes.ConeMesh3D cone = new Ab3d.Meshes.ConeMesh3D(new Point3D(0, -50, 0), 30, 60, 100, 12, true);
                _rootMesh = cone.Geometry;
                break;

            case 7:
                Ab3d.Meshes.ConeMesh3D cone2 = new Ab3d.Meshes.ConeMesh3D(new Point3D(0, -50, 0), 30, 60, 100, 6, false);
                _rootMesh = cone2.Geometry;
                break;

            case 8:
                var readerObj   = new Ab3d.ReaderObj();
                var teapotModel = readerObj.ReadModel3D(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\ObjFiles\Teapot.obj")) as GeometryModel3D;

                if (teapotModel == null)
                {
                    return;
                }

                // Get the teapot MeshGeometry3D
                _rootMesh = (MeshGeometry3D)teapotModel.Geometry;

                break;

            case 9:
                var line = new Ab3d.Visuals.LineVisual3D()
                {
                    StartPosition = new Point3D(0, 0, 0),
                    EndPosition   = new Point3D(100, 0, 0),
                    LineColor     = Colors.Silver,
                    LineThickness = 20
                };

                Show3DLines(line);
                show3DLine = true;
                break;

            case 10:
                var polyLineVisual3D = new Ab3d.Visuals.PolyLineVisual3D()
                {
                    Positions     = new Point3DCollection(new Point3D[] { new Point3D(-75, 50, 0), new Point3D(-25, 0, 0), new Point3D(25, 50, 0), new Point3D(75, 0, 0) }),
                    LineThickness = 20
                };

                Show3DLines(polyLineVisual3D);
                show3DLine = true;
                break;

            case 11:
                // This is the same line as in the previous sample (PolyLineVisual3D), but this time
                // it is created as diconnected list of lines - note that this requires that the positions are duplicated.
                var multiLineVisual3D = new Ab3d.Visuals.MultiLineVisual3D()
                {
                    Positions = new Point3DCollection(new Point3D[] { new Point3D(-75, 50, 0), new Point3D(-25, 0, 0),
                                                                      new Point3D(-25, 0, 0), new Point3D(25, 50, 0),
                                                                      new Point3D(25, 50, 0), new Point3D(75, 0, 0) }),
                    LineThickness = 20
                };

                Show3DLines(multiLineVisual3D);
                show3DLine = true;
                break;

            default:
                _rootMesh = null;
                break;
            }

            // If we were looking at 3D lines before and now we are looking an standard 3D models,
            // we adjust the camera back to the side view (from direct front view)
            if (_isShowing3DLines && !show3DLine)
            {
                Camera1.Heading  = 30;
                Camera1.Attitude = -20;
                Camera1.Distance = 300;
            }

            _isShowing3DLines = show3DLine;


            _rootModel          = new GeometryModel3D();
            _rootModel.Geometry = _rootMesh;
            _rootModel.Material = new DiffuseMaterial(Brushes.DarkBlue);

            ObjectModelVisual.Content = _rootModel;

            Ab3d.Utilities.ModelEventSource3D modelEventSource = new Ab3d.Utilities.ModelEventSource3D();
            modelEventSource.TargetModel3D = _rootModel;
            modelEventSource.MouseClick   += new Ab3d.Common.EventManager3D.MouseButton3DEventHandler(modelEventSource_MouseClick);

            _eventsManager.ResetEventSources3D();
            _eventsManager.RegisterEventSource3D(modelEventSource);

            MainViewport.Cursor = Cursors.Hand;
        }