public ObjectIdRendering() { InitializeComponent(); var boxMesh = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(1, 1, 1), 1, 1, 1).Geometry; int modelsXCount = 20; int modelsYCount = 1; int modelsZCount = 20; var model3DGroup = CreateModel3DGroup(boxMesh, new Point3D(0, 5, 0), new Size3D(500, modelsYCount * 10, 500), 10, modelsXCount, modelsYCount, modelsZCount); MainViewport.Children.Add(model3DGroup.CreateModelVisual3D()); _disposables = new DisposeList(); MainDXViewportView.DXSceneDeviceCreated += MainDxViewportViewOnDxSceneDeviceCreated; this.Unloaded += delegate(object sender, RoutedEventArgs args) { if (_disposables != null) { _disposables.Dispose(); _disposables = null; } MainDXViewportView.Dispose(); }; }
private void CreateTestScene() { var boxMesh = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(1, 1, 1), 1, 1, 1).Geometry; var sphereMesh = new Ab3d.Meshes.SphereMesh3D(new Point3D(0, 0, 0), 0.7, 30).Geometry; int modelsXCount = 10; int modelsYCount = 1; int modelsZCount = 10; _objectsModel3DGroup = new Model3DGroup(); AddModels(_objectsModel3DGroup, boxMesh, new Point3D(0, 5, 0), new Size3D(500, modelsYCount * 10, 500), 10, modelsXCount, modelsYCount, modelsZCount); AddModels(_objectsModel3DGroup, sphereMesh, new Point3D(25, 5, 25), new Size3D(500, modelsYCount * 10, 500), 10, modelsXCount, modelsYCount, modelsZCount); MainViewport.Children.Add(_objectsModel3DGroup.CreateContentVisual3D()); // It would be optimal to use WireGridVisual3D to create a wire grid. // But because WireGridVisual3D creates a MultiLineVisual3D behind the scene, all the lines can have only a single color. // Therefore we create multiple lines for this sample so we can easily change color of individual lines. // And what is more, this way the object id map can get us the hit 3D lines (otherwise the whole MultiLineVisual3D would be hit) // <visuals:WireGridVisual3D CenterPosition="0 0 0" Size="500 500" WidthCellsCount="20" HeightCellsCount="20" LineColor="#555555" LineThickness="5"/> var contentVisual3D = CreateWireGridLines(new Point3D(0, 0, 0), new Size(500, 500), 20, 20, new Vector3D(1, 0, 0), new Vector3D(0, 0, 1), Colors.Gray, 5); MainViewport.Children.Add(contentVisual3D); }
private Model3DGroup Create3DScene(Point3D center, int xCount, int yCount, int zCount, float modelSize) { var semiTransparentBrush = new SolidColorBrush(Color.FromArgb(64, 200, 200, 200)); // alpha = 1/4 var diffuseMaterial = new DiffuseMaterial(semiTransparentBrush); diffuseMaterial.Freeze(); // This will significantly speed up the creation of objects var modelSizeWithMargin = modelSize * 1.2; var size = new Size3D(xCount * modelSizeWithMargin, yCount * modelSizeWithMargin, zCount * modelSizeWithMargin); var instancedData = InstancedMeshGeometry3DTest.CreateInstancesData(center, size, modelSize, xCount, yCount, zCount, false); var model3DGroup = new Model3DGroup(); var boxMesh3D = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(1, 1, 1), 1, 1, 1).Geometry; for (int i = 0; i < instancedData.Length; i++) { var geometryModel3D = new GeometryModel3D(boxMesh3D, diffuseMaterial); geometryModel3D.BackMaterial = diffuseMaterial; geometryModel3D.Transform = new MatrixTransform3D(instancedData[i].World.ToWpfMatrix3D()); model3DGroup.Children.Add(geometryModel3D); } var modelVisual3D = new ModelVisual3D(); modelVisual3D.Content = model3DGroup; MainViewport3D.Children.Add(modelVisual3D); return(model3DGroup); }
private void AddTestModel() { var boxMesh3D = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(1, 1, 1), 1, 1, 1).Geometry; int positionsCount = boxMesh3D.Positions.Count; var bounds = boxMesh3D.Bounds; // Create positionColorsArray that will define colors for each position var positionColorsArray = new Color4[positionsCount]; for (int i = 0; i < positionsCount; i++) { var position = boxMesh3D.Positions[i]; // Get colors based on the relative position inside the Bounds - in range from (0, 0, 0) to (1, 1, 1) float red = (float)((position.X - bounds.X) / bounds.SizeX); float green = (float)((position.Y - bounds.Y) / bounds.SizeY); float blue = (float)((position.Z - bounds.Z) / bounds.SizeZ); // Set Color this position positionColorsArray[i] = new Color4(red, green, blue, alpha: 1.0f); } // Now create the VertexColorMaterial that will be used instead of standard material // and will make the model render with special effect where each vertex can have its own color. _vertexColorMaterial = new VertexColorMaterial() { PositionColors = positionColorsArray, // The PositionColors property is used to specify colors for each vertex // To show specular effect set the specular data here: //SpecularPower = 16, //SpecularColor = Color3.White, //HasSpecularColor = true // If we would update the positionColorsArray very often, then set CreateDynamicBuffer to true //CreateDynamicBuffer = true, }; // Create standard WPF material and set the _vertexColorMaterial to be used when the model is rendered in DXEngine. var vertexColorDiffuseMaterial = new DiffuseMaterial(); vertexColorDiffuseMaterial.SetUsedDXMaterial(_vertexColorMaterial); // Create a GeometryModel3D that will be rendered with _vertexColorMaterial var vertexColorGeometryModel3D = new GeometryModel3D(boxMesh3D, vertexColorDiffuseMaterial); vertexColorGeometryModel3D.Transform = new ScaleTransform3D(100, 50, 80); // Scale the box var vertexColorModelVisual3D = new ModelVisual3D() { Content = vertexColorGeometryModel3D }; MainViewport.Children.Add(vertexColorModelVisual3D); }
private void CreateInstancedObjects() { MainViewport.Children.Clear(); _currentMeshType = (MeshTypes)Enum.Parse(typeof(MeshTypes), (string)ObjectsTypeComboBox.SelectedItem); _screenSize = (float)ScreenSizeComboBox.SelectedItem; MeshGeometry3D mesh; switch (_currentMeshType) { case MeshTypes.Box: mesh = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(1, 1, 1), 1, 1, 1).Geometry; break; case MeshTypes.Sphere: mesh = new Ab3d.Meshes.SphereMesh3D(new Point3D(0, 0, 0), 0.5, 30).Geometry; break; case MeshTypes.Arrow: mesh = new Ab3d.Meshes.ArrowMesh3D(new Point3D(-0.5, 0, 0), new Point3D(0.5, 0, 0), 0.1, 0.2, 45, 30, false).Geometry; break; default: mesh = null; break; } var instancedData = GetInstancedData(_currentMeshType, _screenSize); _instancedMeshGeometryVisual3D = new InstancedMeshGeometryVisual3D(mesh); _instancedMeshGeometryVisual3D.InstancesData = instancedData; // To enable screen-space scaling, set the UseScreenSpaceScaling to true. // // IMPORTANT: // For this to work correctly, the size of the instance mesh must be 1 and the center of the mesh must be at (0, 0, 0). // In this case the mesh will be scaled correctly to the screen size that is defined in the instance matrix's scale component. _instancedMeshGeometryVisual3D.UseScreenSpaceScaling = UseScreenSpaceScaleCheckBox.IsChecked ?? false; MainViewport.Children.Add(_instancedMeshGeometryVisual3D); _instanceWorldPositions = null; // Reset array of instance positions that is used for finding the closest instance in screen coordinates _selectedInstanceIndex = -1; // Because we have cleared all MainViewport.Children, this also removed the camera's light. // Call Refresh to recreate the light Camera1.Refresh(); }
private void CreateTestScene() { var rootModel3DGroup = new Model3DGroup(); var greenMaterial = new DiffuseMaterial(Brushes.Green); var redMaterial = new DiffuseMaterial(Brushes.Red); var boxMesh3D = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(1, 1, 1), 1, 1, 1).Geometry; // Create 7 x 7 boxes with different height for (int y = -3; y <= 3; y++) { for (int x = -3; x <= 3; x++) { // Height is based on the distance from the center double height = (5 - Math.Sqrt(x * x + y * y)) * 60; // Instead of creating MeshGeometry3D for each box, we reuse the standard box mesh //var boxGeometryModel3D = Ab3d.Models.Model3DFactory.CreateBox(centerPosition: new Point3D(x * 100, height / 2, y * 100), // size: new Size3D(80, height, 80), // material: height > 200 ? redMaterial : greenMaterial); // Create the 3D Box var boxGeometryModel3D = new GeometryModel3D(boxMesh3D, material: height > 200 ? redMaterial : greenMaterial); // Scale: 80, height, 80 // Translate: x * 100, height / 2, y * 100 boxGeometryModel3D.Transform = new MatrixTransform3D(new Matrix3D(80, 0, 0, 0, 0, height, 0, 0, 0, 0, 80, 0, x * 100, height / 2, y * 100, 1)); // To preserve the object names we can fill the names into the _namedObjects dictionary boxGeometryModel3D.SetName(string.Format("Box_{0}_{1}", x + 4, y + 4)); rootModel3DGroup.Children.Add(boxGeometryModel3D); } } ContentModelVisual3D.Content = rootModel3DGroup; _rootModel3D = rootModel3DGroup; }
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; }
private void CreateScene() { var boxMeshGeometry3D = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(BoxSize, BoxSize, BoxSize), 1, 1, 1).Geometry; _oneMeshTriangleIndicesCount = boxMeshGeometry3D.TriangleIndices.Count; PositionNormalTexture[] vertexBuffer; int[] indexBuffer; CreateMultiMeshBuffer(center: new Vector3(0, 0, 0), size: new Vector3(XCount * (BoxSize + BoxesMargin), YCount * (BoxSize + BoxesMargin), ZCount * (BoxSize + BoxesMargin)), xCount: XCount, yCount: YCount, zCount: ZCount, meshGeometry3D: boxMeshGeometry3D, vertexBuffer: out vertexBuffer, indexBuffer: out indexBuffer); _multiMaterialMesh = new SimpleMesh <PositionNormalTexture>(vertexBuffer, indexBuffer, inputLayoutType: InputLayoutType.Position | InputLayoutType.Normal | InputLayoutType.TextureCoordinate); _indexBufferLength = indexBuffer.Length; // i1 is at 1/4 of the height of the box _firstColorIndex = (int)(_indexBufferLength / 4); // i2 is at 3/4 of the height _secondColorIndex = _firstColorIndex * 3; _multiMaterialMesh.SubMeshes = new SubMesh[] { new SubMesh("SubMesh1") { MaterialIndex = 0, StartIndexLocation = 0, IndexCount = _firstColorIndex }, new SubMesh("SubMesh2") { MaterialIndex = 1, StartIndexLocation = _firstColorIndex, IndexCount = _secondColorIndex - _firstColorIndex }, new SubMesh("SubMesh3") { MaterialIndex = 2, StartIndexLocation = _secondColorIndex, IndexCount = _indexBufferLength - _secondColorIndex }, }; _disposables.Add(_multiMaterialMesh); var materials = new Ab3d.DirectX.Material[] { new Ab3d.DirectX.Materials.StandardMaterial() { DiffuseColor = Colors.DimGray.ToColor3() }, new Ab3d.DirectX.Materials.StandardMaterial() { DiffuseColor = Colors.Silver.ToColor3() }, new Ab3d.DirectX.Materials.StandardMaterial() { DiffuseColor = Colors.Gold.ToColor3() }, }; _meshObjectNode = new Ab3d.DirectX.MeshObjectNode(_multiMaterialMesh, materials); _disposables.Add(_meshObjectNode); // Use SceneNodeVisual3D to show SceneNode in DXViewportView var sceneNodeVisual3D = new SceneNodeVisual3D(_meshObjectNode); MainViewport.Children.Add(sceneNodeVisual3D); }
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; }
private void CreateBoxes(Model3DGroup rootGroup, Dictionary <object, string> objectNames) { GeometryModel3D geometryModel3D; DiffuseMaterial material; Color color; Ab3d.Meshes.BoxMesh3D boxMesh = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(80, 80, 80), 1, 1, 1); string objectName; string colorName; double offsetX, offsetY, offsetZ; for (int x = 0; x < 3; x++) { offsetX = -100 + x * 100; if (x == 0) { color = Color.FromArgb(255, 255, 0, 0); colorName = "red"; } else if (x == 1) { color = Color.FromArgb(255, 0, 255, 0); colorName = "green"; } else { color = Color.FromArgb(255, 0, 0, 255); colorName = "blue"; } for (int y = 0; y < 3; y++) { offsetY = -100 + y * 100; for (int z = 0; z < 3; z++) { offsetZ = -100 + z * 100; if (z == 0) { color.A = 80; } else if (z == 1) { color.A = 160; } else { color.A = 255; } material = new DiffuseMaterial(new SolidColorBrush(color)); geometryModel3D = new GeometryModel3D(boxMesh.Geometry, material); if (z != 2) { geometryModel3D.BackMaterial = material; // Set BackMaterial to transparent models } geometryModel3D.Transform = new TranslateTransform3D(offsetX, offsetY, offsetZ); rootGroup.Children.Add(geometryModel3D); objectName = string.Format("Box_{0}_{1}_{2}", colorName, color.A, y + 1); objectNames.Add(geometryModel3D, objectName); } } } }
// See also: // - Objects3D/BooleanOperationsSample to see other boolean operations // - Utilities/TextureCoordinatesGeneratorSample to see other options to define TextureCoordinates that are needed to show texture images public ModelingWithBooleanOperations() { InitializeComponent(); _orangeMaterial = new MaterialGroup(); _orangeMaterial.Children.Add(new DiffuseMaterial(Brushes.Orange)); _orangeMaterial.Children.Add(new SpecularMaterial(Brushes.White, 16)); // We will start with a simple box // Create it manually with MeshGeometry3D MeshGeometry3D initialBoxMesh3D = new Ab3d.Meshes.BoxMesh3D(new Point3D(-100, 25, 0), new Size3D(200, 50, 100), 1, 1, 1).Geometry; // Without boolean operations, we could simply create the box with: //var boxVisual3D = new BoxVisual3D() //{ // CenterPosition = new Point3D(-100, 25, 0), // Size = new Size3D(200, 50, 100), // UseCachedMeshGeometry3D = false, // we should not use the cached // Material = _orangeMaterial //}; // Define MeshGeometry3D objects that will be used for subtractions var centerSphereMesh = new Ab3d.Meshes.SphereMesh3D(new Point3D(-100, 50, 0), 40, 16).Geometry; var box1Mesh = new Ab3d.Meshes.BoxMesh3D(new Point3D(-180, 0, -30), new Size3D(10, 200, 10), 1, 1, 1).Geometry; var box2Mesh = new Ab3d.Meshes.BoxMesh3D(new Point3D(-180, 0, 0), new Size3D(10, 200, 10), 1, 1, 1).Geometry; var box3Mesh = new Ab3d.Meshes.BoxMesh3D(new Point3D(-180, 0, 30), new Size3D(10, 200, 10), 1, 1, 1).Geometry; var cylinder1Mesh3D = new Ab3d.Meshes.CylinderMesh3D(new Point3D(-20, 0, -30), 8, 200, segments: 16, isSmooth: false).Geometry; var cylinder2Mesh3D = new Ab3d.Meshes.CylinderMesh3D(new Point3D(-20, 0, 0), 8, 200, segments: 16, isSmooth: false).Geometry; var cylinder3Mesh3D = new Ab3d.Meshes.CylinderMesh3D(new Point3D(-20, 0, 30), 8, 200, segments: 16, isSmooth: false).Geometry; // When doing multiple boolean operations one after another, // it is recommended (and mush faster) to use BooleanMesh3D object. var booleanMesh3D = new Ab3d.Meshes.BooleanMesh3D(initialBoxMesh3D); booleanMesh3D.Subtract(centerSphereMesh); booleanMesh3D.Subtract(box1Mesh); booleanMesh3D.Subtract(box2Mesh); booleanMesh3D.Subtract(box3Mesh); booleanMesh3D.Subtract(cylinder1Mesh3D); booleanMesh3D.Subtract(cylinder2Mesh3D); booleanMesh3D.Subtract(cylinder3Mesh3D); // It is also possible to use Subtract method on BoxVisual3D object: //boxVisual3D.Subtract(centerSphereMesh); //boxVisual3D.Subtract(box1Mesh); //boxVisual3D.Subtract(box2Mesh); //boxVisual3D.Subtract(box3Mesh); //boxVisual3D.Subtract(cylinder1Mesh3D); //boxVisual3D.Subtract(cylinder2Mesh3D); //boxVisual3D.Subtract(cylinder3Mesh3D); // We could also use the static methods on Ab3d.Utilities.MeshBooleanOperations class: //Ab3d.Utilities.MeshBooleanOperations.Subtract(boxVisual3D, sphereMesh); //Ab3d.Utilities.MeshBooleanOperations.Subtract(boxVisual3D, boxMesh); // When calling the Geometry getter, the BooleanMesh3D converts the internal object into MeshGeometry3D. var meshGeometry3D = booleanMesh3D.Geometry; var initialGeometryModel3D = new GeometryModel3D(meshGeometry3D, _orangeMaterial); var boxVisual3D = initialGeometryModel3D.CreateModelVisual3D(); // Now add the changed box to the scene MainViewport.Children.Add(boxVisual3D); // When working with more complex meshes, the boolean operations can take some time. // To prevent blocking UI thread, we can do the boolean operations in the background thread. // To do this we need to freeze the MeshGeometry3D that are send to the background thread and back to UI thread. // // The following code is using spheres with 30 segments to demonstrate a longer boolean operations. // // First define the original MeshGeometry3D initialBoxMesh3D = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 25, 0), new Size3D(100, 50, 100), 1, 1, 1).Geometry; ShowNewOriginalMesh(initialBoxMesh3D); var initialBooleanMesh3D = new Ab3d.Meshes.BooleanMesh3D(initialBoxMesh3D); var sphereCenters = new Point3D[] { new Point3D(-50, 50, 50), new Point3D(50, 50, 50), new Point3D(50, 50, -50), new Point3D(-50, 50, -50), new Point3D(-50, 0, 50), new Point3D(50, 0, 50), new Point3D(50, 0, -50), new Point3D(-50, 0, -50) }; // We can create the MeshGeometry3D and prepare the BooleanMesh3D in parallel - each can be created in its own thread var sphereBooleanMeshes = sphereCenters.AsParallel().Select(sphereCenter => { //System.Diagnostics.Debug.WriteLine($"Start creating SphereMesh3D with {sphereCenter} on {System.Threading.Thread.CurrentThread.ManagedThreadId}"); var sphereMeshGeometry3D = new Ab3d.Meshes.SphereMesh3D(sphereCenter, radius: 15, segments: 30).Geometry; var sphereBooleanMesh3D = new Ab3d.Meshes.BooleanMesh3D(sphereMeshGeometry3D); return(sphereBooleanMesh3D); }); // After that we can subtract each of the sphere meshes from the initialBooleanMesh3D. // This can be done in background thread (we use Dispatcher.Invoke to "send" the mesh to the UI thread) Task.Factory.StartNew(() => { // Note the order in which the sphereBooleanMesh are created is not determined (as the BooleanMesh3D are created, they get available to the foreach) foreach (var sphereBooleanMesh in sphereBooleanMeshes) { // Subtract the sphereBooleanMesh from the initialBooleanMesh3D initialBooleanMesh3D.Subtract(sphereBooleanMesh); // Get the MeshGeometry3D var mesh = initialBooleanMesh3D.Geometry; // Freeze the MeshGeometry3D // This will allow using the mesh in UI thread (different thread as the mesh was created) mesh.Freeze(); // Send it to UI thread this.Dispatcher.BeginInvoke(new Action(() => { ShowNewOriginalMesh(mesh); })); } }) // After all the boolean operations are completed, we generate texture coordinates // so we will be able to use texture image as material (meshes that are created with boolean operations do not have texture coordinates defined) .ContinueWith(_ => GenerateTextureCoordinates(), TaskScheduler.FromCurrentSynchronizationContext()); // The last one is run on UI thread }
private void CreateTestModels() { _rootModelVisual3D = new ModelVisual3D(); MainViewport3D.Children.Add(_rootModelVisual3D); // SphereVisual3D _sphereVisual3D = new Ab3d.Visuals.SphereVisual3D() { CenterPosition = new Point3D(-50, 0, -50), Radius = 30, Material = new DiffuseMaterial(Brushes.Silver) }; _sphereVisual3D.SetName("SphereVisual3D"); _rootModelVisual3D.Children.Add(_sphereVisual3D); var readerObj = new ReaderObj(); var teapotModel = readerObj.ReadModel3D(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\Models\teapot-hires.obj")); Ab3d.Utilities.ModelUtils.CenterAndScaleModel3D(teapotModel, centerPosition: new Point3D(50, 0, -50), finalSize: new Size3D(80, 80, 80), preserveAspectRatio: true); _teapotModelVisual3D = new ModelVisual3D() { Content = teapotModel }; teapotModel.SetName("teapot Model3D"); _teapotModelVisual3D.SetName("teapot ModelVisual3D"); _rootModelVisual3D.Children.Add(_teapotModelVisual3D); // InstancedMeshGeometryVisual3D var boxMesh3D = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(6, 6, 6), 1, 1, 1); InstanceData[] instancedData = DXEnginePerformance.InstancedMeshGeometry3DTest.CreateInstancesData(center: new Point3D(-50, 0, 50), size: new Size3D(80, 50, 80), modelScaleFactor: 1, xCount: 5, yCount: 1, zCount: 5, useTransparency: false); _instancedMeshGeometryVisual3D = new InstancedMeshGeometryVisual3D(boxMesh3D.Geometry); _instancedMeshGeometryVisual3D.InstancesData = instancedData; _instancedMeshGeometryVisual3D.SetName("InstancedMeshGeometryVisual3D"); _rootModelVisual3D.Children.Add(_instancedMeshGeometryVisual3D); // MeshObjectNode and SceneNodeVisual3D var meshGeometry3D = new Ab3d.Meshes.PyramidMesh3D(new Point3D(50, -20, 50), new Size3D(80, 40, 80)).Geometry; var dxMeshGeometry3D = new Ab3d.DirectX.Models.DXMeshGeometry3D(meshGeometry3D); var standardMaterial = new StandardMaterial() { DiffuseColor = Colors.Gold.ToColor3() }; _pyramidMeshObjectNode = new Ab3d.DirectX.MeshObjectNode(dxMeshGeometry3D, standardMaterial); _disposables.Add(dxMeshGeometry3D); _disposables.Add(_pyramidMeshObjectNode); var sceneNodeVisual3D = new SceneNodeVisual3D(_pyramidMeshObjectNode); sceneNodeVisual3D.SetName("SceneNodeVisual3D"); _rootModelVisual3D.Children.Add(sceneNodeVisual3D); }
private void GenerateSampleObjects() { // We will show multiple instances of box MeshGeometry3D that is created here. // // IMPORTANT: // // It is very important to specify the correct position and size of the mesh. // The size should be one unit so that when you scale this mesh in instance data, // the scale factor will tell you the final size (for example xScale = 3 would render box with xSize set to 3). // // The position is even more important because when you will scale and rotate the mesh, // the mesh will be scaled and rotated around (0, 0, 0). // So if center of mesh is at (0, 0, 0), then the mesh will be also scale in all directions. // But if left edge is at (0, 0, 0), then the object will scale to the right (all coordinates are multiplied by the scale). // // What is more, the position that is at (0, 0, 0) in the original mesh will be positioned at the position // defined in the World transform by the M41, M42, M43 fields. // So if center of the mesh is at (0, 0, 0) - as in our case - then M41, M42, M43 will define the position of the center. // But if left-bottom-front edge would be at (0, 0, 0) - if we would use "centerPosition: new Point3D(0.5, 0.5, 0.5)" - // then M41, M42, M43 will define the position of the left-bottom-front edge when the box is shown. // // See also comments in CalculateMatrixFromPositionsAndSize method. Point3D boxCenterPosition = CenterBoxMeshToCoordinateCenter ? new Point3D(0, 0, 0) : new Point3D(0.5, 0, 0); var boxMeshGeometry3D = new Ab3d.Meshes.BoxMesh3D(centerPosition: boxCenterPosition, size: new Size3D(1, 1, 1), xSegments: 1, ySegments: 1, zSegments: 1).Geometry; // Uncomment the following line to see how an ArrowMesh3D would look like (note that arrow part is also scaled so ArrowMesh3D is not a very good candidate for mesh used for instancing when scale is not uniform) //boxMeshGeometry3D = new Ab3d.Meshes.ArrowMesh3D(startPosition: new Point3D(0, 0, 0), endPosition: new Point3D(1, 0, 0), radius: 0.1f, arrowRadius: 0.2f, arrowAngle: 45, segments: 10, generateTextureCoordinates: false).Geometry; // Create an instance of InstancedMeshGeometryVisual3D var instancedMeshGeometryVisual3D = new InstancedMeshGeometryVisual3D(boxMeshGeometry3D); // Create an array of InstanceData with the matrices define in the _matrices list and Green color. var instanceData = new InstanceData[_samplesData.Count]; for (int i = 0; i < _samplesData.Count; i++) { instanceData[i] = new InstanceData(_samplesData[i].Matrix, Colors.Green.ToColor4()); instanceData[i].World.M43 -= SamplesDistance * i; var wireGridVisual3D = new WireGridVisual3D() { CenterPosition = new Point3D(0, 0, -SamplesDistance * i), Size = new Size(4, 4), WidthCellsCount = 4, HeightCellsCount = 4, LineColor = Colors.Gray, LineThickness = 1 }; MainViewport.Children.Add(wireGridVisual3D); var yAxisLineVisual3D = new LineVisual3D() { StartPosition = wireGridVisual3D.CenterPosition, EndPosition = wireGridVisual3D.CenterPosition + new Vector3D(0, 1.2, 0), LineColor = wireGridVisual3D.LineColor, LineThickness = wireGridVisual3D.LineThickness, EndLineCap = LineCap.ArrowAnchor }; MainViewport.Children.Add(yAxisLineVisual3D); } instancedMeshGeometryVisual3D.InstancesData = instanceData; MainViewport.Children.Add(instancedMeshGeometryVisual3D); }
private void MainDXViewportViewOnDXSceneDeviceCreated(object sender, EventArgs e) { var instancedData = CreateInstancesData(center: new Point3D(0, 0, 0), size: new Size3D(4 * XInstancesCount, 4 * YInstancesCount, 4 * ZInstancesCount), modelScaleFactor: 1, xCount: XInstancesCount, yCount: YInstancesCount, zCount: ZInstancesCount, useTransparency: false); // Update colors int dataCount = instancedData.Length; for (int i = 0; i < dataCount; i++) { float percentage = 1.0f - (float)i / (float)dataCount; instancedData[i].DiffuseColor = new Color4(red: percentage, green: 1, blue: percentage, alpha: 1); } var boxMeshGeometry = new Ab3d.Meshes.BoxMesh3D(centerPosition: new Point3D(0, 0, 0), size: new Size3D(3, 3, 3), xSegments: 1, ySegments: 1, zSegments: 1).Geometry; // The first InstancedMeshGeometry3DNode will get the instancedData and // will also create the DirectX instance buffer. _instancedMeshGeometry3DNode1 = new InstancedMeshGeometry3DNode(boxMeshGeometry); _instancedMeshGeometry3DNode1.SetInstanceData(instancedData); // Manually call InitializeResources. // For this to work, the dxViewportView.DXScene must be set. // This is the reason why this method is called inside a DXViewportView.DXSceneDeviceCreated event handler. _instancedMeshGeometry3DNode1.InitializeResources(MainDXViewportView.DXScene); _disposables.Add(_instancedMeshGeometry3DNode1); var instanceBuffer = _instancedMeshGeometry3DNode1.GetInstanceBuffer(); if (instanceBuffer == null) { throw new Exception("GetInstanceBuffer returned null"); // Probably DXScene is not initialized } // Now create another 2 InstancedMeshGeometry3DNode objects // and initialize it with already created instanceBuffer // The next InstancedMeshGeometry3DNode will be also initialized so // that all instances will be rendered with red color instead of the color defined in the instances data. _instancedMeshGeometry3DNode2 = new InstancedMeshGeometry3DNode(boxMeshGeometry); _instancedMeshGeometry3DNode2.SetInstanceBuffer(instanceBuffer, InstanceData.SizeInBytes, instancedData.Length, instancedData); _instancedMeshGeometry3DNode2.UseSingleObjectColor(Colors.Red.ToColor4()); _disposables.Add(_instancedMeshGeometry3DNode2); // The last InstancedMeshGeometry3DNode will render last part of the instances with the color defined in the instance data. _instancedMeshGeometry3DNode3 = new InstancedMeshGeometry3DNode(boxMeshGeometry); _instancedMeshGeometry3DNode3.SetInstanceBuffer(instanceBuffer, InstanceData.SizeInBytes, instancedData.Length, instancedData); _disposables.Add(_instancedMeshGeometry3DNode3); // Set StartInstanceIndex and InstancesCount _startTime = DateTime.Now; _lastStartRowIndex = int.MinValue; UpdateHiddenInstancesPositions(); var rootSceneNode = new SceneNode(); rootSceneNode.AddChild(_instancedMeshGeometry3DNode1); rootSceneNode.AddChild(_instancedMeshGeometry3DNode2); rootSceneNode.AddChild(_instancedMeshGeometry3DNode3); var sceneNodeVisual3D = new SceneNodeVisual3D(rootSceneNode); MainViewport.Children.Add(sceneNodeVisual3D); }
private void CreateTestScene(Viewport3D wpfViewport3D) { var boxMaterial = new DiffuseMaterial(Brushes.Orange); var sphereMaterial = new MaterialGroup(); sphereMaterial.Children.Add(new DiffuseMaterial(Brushes.SkyBlue)); sphereMaterial.Children.Add(new SpecularMaterial(Brushes.White, 20)); var lightMaterialGroup = new MaterialGroup(); lightMaterialGroup.Children.Add(new DiffuseMaterial(Brushes.Black)); lightMaterialGroup.Children.Add(new EmissiveMaterial(Brushes.Yellow)); var objectsGroup = new Model3DGroup(); //var boxMesh = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(30, 30, 30), 1, 1, 1).Geometry; //var sphereMesh = new Ab3d.Meshes.SphereMesh3D(new Point3D(0, 0, 0), 15, 20, false).Geometry; //for (int y = 0; y < 5; y++) //{ // for (int x = -200; x <= 200; x += 100) // { // for (int z = -200; z <= 200; z += 100) // { // var geometryModel3D = new GeometryModel3D(); // if ((y % 2) == 0) // { // geometryModel3D.Geometry = boxMesh; // geometryModel3D.Material = boxMaterial; // } // else // { // geometryModel3D.Geometry = sphereMesh; // geometryModel3D.Material = sphereMaterial; // } // geometryModel3D.Transform = new TranslateTransform3D(x, y * 50, z); // objectsGroup.Children.Add(geometryModel3D); // } // } //} var boxMesh = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(1, 1, 1), 1, 1, 1).Geometry; var sphereMesh = new Ab3d.Meshes.SphereMesh3D(new Point3D(0, 0, 0), 10, 20, false).Geometry; double yPos = 0; double firstSize = 50; for (int y = 0; y < 5; y++) { int samples = (y * 2) + 2; int halfSamples = samples / 2; double size = 400 / (samples * 1.5); if (y == 0) { firstSize = size; } double xPos = -200; for (int x = -halfSamples; x <= halfSamples; x++) { double zPos = -200; for (int z = -halfSamples; z <= halfSamples; z++) { var geometryModel3D = new GeometryModel3D(); geometryModel3D.Geometry = boxMesh; geometryModel3D.Material = boxMaterial; var transform3DGroup = new Transform3DGroup(); transform3DGroup.Children.Add(new ScaleTransform3D(size, size, size)); transform3DGroup.Children.Add(new TranslateTransform3D(xPos, yPos, zPos)); geometryModel3D.Transform = transform3DGroup; objectsGroup.Children.Add(geometryModel3D); zPos += size * 1.5; } xPos += size * 1.5; } yPos += size + y * 7 + 10; } for (int a = 0; a < 360; a += 20) { double rad = MathUtil.DegreesToRadians(a); double x = Math.Sin(rad) * 600; double z = Math.Cos(rad) * 600; var geometryModel3D = new GeometryModel3D(); geometryModel3D.Geometry = sphereMesh; geometryModel3D.Material = sphereMaterial; var transform3DGroup = new Transform3DGroup(); transform3DGroup.Children.Add(new ScaleTransform3D(8, 8, 8)); transform3DGroup.Children.Add(new TranslateTransform3D(x, 20, z)); geometryModel3D.Transform = transform3DGroup; objectsGroup.Children.Add(geometryModel3D); } var bottomBoxModel3D = new GeometryModel3D(); bottomBoxModel3D.Geometry = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, -(firstSize / 2), 0), new Size3D(2000, 10, 2000), 1, 1, 1).Geometry; //bottomBoxModel3D.Geometry = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, -(firstSize / 2), 0), new Size3D(2000, 10, 2000), 50, 1, 50).Geometry; // To see at least some spot light on bottom box in WPF, create the box from 50 x 50 mesh (or more) bottomBoxModel3D.Material = new DiffuseMaterial(Brushes.Silver); objectsGroup.Children.Add(bottomBoxModel3D); var wireGrid = new Ab3d.Visuals.WireGridVisual3D(); wireGrid.CenterPosition = new Point3D(0, -(firstSize / 2) + 11, 0); wireGrid.Size = new Size(1800, 1800); wireGrid.WidthCellsCount = 9; wireGrid.HeightCellsCount = 9; wireGrid.LineColor = Colors.SkyBlue; wireGrid.LineThickness = 3; wpfViewport3D.Children.Add(wireGrid); var lightsGroup = new Model3DGroup(); _spotLightModel = new GeometryModel3D(); _spotLightModel.Geometry = sphereMesh; _spotLightModel.Material = lightMaterialGroup; _spotLightTranslate = new TranslateTransform3D(_wpfSpotLight.Position.X, _wpfSpotLight.Position.Y, _wpfSpotLight.Position.Z); _spotLightModel.Transform = _spotLightTranslate; lightsGroup.Children.Add(_spotLightModel); _pointLightModel = new GeometryModel3D(); _pointLightModel.Geometry = sphereMesh; _pointLightModel.Material = lightMaterialGroup; _pointLightTranslate = new TranslateTransform3D(_wpfPointLight1.Position.X, _wpfPointLight1.Position.Y, _wpfPointLight1.Position.Z); _pointLightModel.Transform = _pointLightTranslate; lightsGroup.Children.Add(_pointLightModel); var modelVisual3D = new ModelVisual3D(); modelVisual3D.Content = objectsGroup; wpfViewport3D.Children.Add(modelVisual3D); var lightsVisual3D = new ModelVisual3D(); lightsVisual3D.Content = lightsGroup; wpfViewport3D.Children.Add(lightsVisual3D); }