private PhysicallyBasedMaterial CreatePbrMaterial(AssimpMaterial assimpMaterial, string filePath, string customTexturesFolder, bool useStrictFileNameMatch, bool supportDDSTextures)
        {
            PhysicallyBasedMaterial physicallyBasedMaterial;

            if (_dxMaterials.TryGetValue(assimpMaterial, out physicallyBasedMaterial)) // Is PhysicallyBasedMaterial already creared
            {
                Log($"  Material: {assimpMaterial.Name ?? ""} (already defined)");
                return(physicallyBasedMaterial);
            }

            //if (!assimpMaterial.HasTextureDiffuse)
            //{
            //    Log($"  Material {assimpMaterial.Name ?? ""} does not define a diffuse texture");
            //    return null;
            //}


            Log($"  Material {assimpMaterial.Name ?? ""}:");


            physicallyBasedMaterial = new PhysicallyBasedMaterial();

            // When materials has diffuse texture defined, then we also try to find other PBR textures
            if (assimpMaterial.HasTextureDiffuse)
            {
                AddPBRTextures(assimpMaterial, filePath, customTexturesFolder, useStrictFileNameMatch, supportDDSTextures, physicallyBasedMaterial);
            }


            // Set BaseColor based on the DiffuseColor
            if (assimpMaterial.HasColorDiffuse)
            {
                physicallyBasedMaterial.BaseColor = new Color4(assimpMaterial.ColorDiffuse.R, assimpMaterial.ColorDiffuse.G, assimpMaterial.ColorDiffuse.B, assimpMaterial.ColorDiffuse.A);
            }

            // When there is no Metalness texture defined, then set Metalness to zero - use plastic
            if (!physicallyBasedMaterial.HasTextureMap(TextureMapTypes.Metalness))
            {
                physicallyBasedMaterial.Metalness = 0;
            }


            _disposables.Add(physicallyBasedMaterial);
            _dxMaterials.Add(assimpMaterial, physicallyBasedMaterial);

            AddTextureMapSelections(assimpMaterial.Name, physicallyBasedMaterial);

            return(physicallyBasedMaterial);
        }
        public TextureMapSelectionControl(IMultiMapMaterial material, TextureMapTypes textureMapType, string baseFolder = null)
        {
            Material = material;
            _physicallyBasedMaterial = material as PhysicallyBasedMaterial;

            TextureMapType = textureMapType;

            if (baseFolder != null && !baseFolder.EndsWith("\\") && !baseFolder.EndsWith("/"))
            {
                baseFolder += '\\';
            }

            BaseFolder = baseFolder;

            _textureMapInfo = Material.TextureMaps.FirstOrDefault(m => m.MapType == TextureMapType);


            InitializeComponent();

            ShowTextureTextBox = true;



            if (_physicallyBasedMaterial != null)
            {
                ShowFilter = textureMapType == TextureMapTypes.Metalness ||
                             textureMapType == TextureMapTypes.Glossiness ||
                             textureMapType == TextureMapTypes.Roughness ||
                             textureMapType == TextureMapTypes.MetalnessRoughness ||
                             textureMapType == TextureMapTypes.AmbientOcclusion;

                ShowMask = textureMapType == TextureMapTypes.Albedo ||
                           textureMapType == TextureMapTypes.BaseColor ||
                           textureMapType == TextureMapTypes.DiffuseColor;

                if (textureMapType == TextureMapTypes.Metalness || textureMapType == TextureMapTypes.MetalnessRoughness)
                {
                    CurrentFilterValue = _physicallyBasedMaterial.Metalness;
                }

                if (textureMapType == TextureMapTypes.Roughness || textureMapType == TextureMapTypes.MetalnessRoughness)
                {
                    CurrentFilterValue = _physicallyBasedMaterial.Roughness;
                }

                if (ShowMask)
                {
                    CurrentMaskColor = _physicallyBasedMaterial.BaseColor.ToWpfColor();
                }
            }
            else
            {
                ShowFilter = false;
                ShowMask   = false;
            }

            // To add support for drop into TextBox, we need to use PreviewDrop and PreviewDragOver events in DragAndDropHelper
            //var dragAndDropHelper = new DragAndDropHelper(FileNameTextBox, ".*");
            //dragAndDropHelper.FileDroped += delegate (object sender, FileDropedEventArgs e)
            //{
            //    FileNameTextBox.Text = e.FileName;
            //    MasterCheckBox.IsChecked = true;

            //    LoadCurrentTexture();
            //};


            MapTypeTextBlock.Text = textureMapType.ToString();

            if (_textureMapInfo == null)
            {
                FileNameTextBox.Text      = "";
                TextureCheckBox.IsChecked = false;
            }
            else
            {
                if (BaseFolder != null && _textureMapInfo.TextureResourceName.StartsWith(BaseFolder))
                {
                    FileNameTextBox.Text = _textureMapInfo.TextureResourceName.Substring(BaseFolder.Length);
                }
                else
                {
                    FileNameTextBox.Text = _textureMapInfo.TextureResourceName;
                }

                TextureCheckBox.IsChecked = true;
            }

            UpdateMaskHeadingTextBlock();
        }
        private PhysicallyBasedMaterial CreatePbrMaterial(AssimpMaterial assimpMaterial, string filePath, string customTexturesFolder, bool useStrictFileNameMatch, bool supportDDSTextures)
        {
            PhysicallyBasedMaterial physicallyBasedMaterial;

            if (_dxMaterials.TryGetValue(assimpMaterial, out physicallyBasedMaterial))
            {
                Log($"  Material: {assimpMaterial.Name ?? ""} (already defined)");
                return(physicallyBasedMaterial);
            }

            if (!assimpMaterial.HasTextureDiffuse)
            {
                Log($"  Material {assimpMaterial.Name ?? ""} does not define a diffuse texture");
                return(null);
            }


            Log($"  Material {assimpMaterial.Name ?? ""}:");

            //PhysicallyBasedMaterial physicallyBasedMaterial;
            string diffuseTextureFileName = assimpMaterial.TextureDiffuse.FilePath;

            if (!string.IsNullOrEmpty(customTexturesFolder))
            {
                diffuseTextureFileName = System.IO.Path.Combine(customTexturesFolder, System.IO.Path.GetFileName(diffuseTextureFileName));
            }
            else if (!System.IO.Path.IsPathRooted(diffuseTextureFileName))
            {
                diffuseTextureFileName = System.IO.Path.Combine(filePath, diffuseTextureFileName);
            }

            string folderName = System.IO.Path.GetDirectoryName(diffuseTextureFileName);

            if (!System.IO.Directory.Exists(folderName))
            {
                Log($"  Folder for diffuse texture does not exist: {folderName ?? ""}:");
                return(null);
            }


            if (_folderImageFiles == null)
            {
                _folderImageFiles = new Dictionary <string, string[]>();
            }

            string[] allFilesInFolder;

            if (!_folderImageFiles.TryGetValue(folderName, out allFilesInFolder))
            {
                allFilesInFolder = System.IO.Directory.GetFiles(folderName, "*.*", SearchOption.TopDirectoryOnly);
                _folderImageFiles.Add(folderName, allFilesInFolder);
            }


            string fileNameWithoutKnownSuffix = KnownTextureFiles.GetFileNameWithoutKnownSuffix(diffuseTextureFileName);

            // Get material files that start with the diffuse texture file name without a suffix
            List <string> materialFiles;

            if (useStrictFileNameMatch)
            {
                materialFiles = allFilesInFolder.Where(f => fileNameWithoutKnownSuffix == KnownTextureFiles.GetFileNameWithoutKnownSuffix(f)).ToList();
            }
            else
            {
                materialFiles = allFilesInFolder.Where(f => f.IndexOf(fileNameWithoutKnownSuffix, 0, StringComparison.OrdinalIgnoreCase) != -1).ToList();
            }


            _textureFiles.Clear();

            if (materialFiles.Count == 0)
            {
                Log($"   Folder ({folderName}) for {assimpMaterial.Name ?? ""} material does not define any texture files");
                return(null);
            }
            else
            {
                bool hasDiffuseTexture = false;
                foreach (var materialFile in materialFiles)
                {
                    if (!TextureLoader.IsSupportedFile(materialFile, supportDDSTextures)) // Skip unsupported files
                    {
                        continue;
                    }

                    var textureMapType = KnownTextureFiles.GetTextureType(materialFile);
                    if (textureMapType == TextureMapTypes.Unknown)
                    {
                        if (!hasDiffuseTexture)
                        {
                            textureMapType = TextureMapTypes.DiffuseColor; // First unknown file type is considered to be diffuse texture file
                        }
                        else
                        {
                            continue; // Unknown file type
                        }
                    }

                    bool isDiffuseTexture = (textureMapType == TextureMapTypes.DiffuseColor ||
                                             textureMapType == TextureMapTypes.Albedo ||
                                             textureMapType == TextureMapTypes.BaseColor);

                    string existingTextureFileName;
                    if (_textureFiles.TryGetValue(textureMapType, out existingTextureFileName))
                    {
                        // Map for this texture type already exist
                        var existingFileExtension = System.IO.Path.GetExtension(existingTextureFileName);
                        if (existingFileExtension != null && existingFileExtension.Equals(".dds", StringComparison.OrdinalIgnoreCase))
                        {
                            continue; // DDS texture already found for this texture type - we will use existing dds texture
                        }
                    }


                    hasDiffuseTexture |= isDiffuseTexture;

                    _textureFiles.Add(textureMapType, materialFile);

                    Log("    " + textureMapType + ": " + System.IO.Path.GetFileName(materialFile));
                }

                if (_textureFiles.Count > 0)
                {
                    physicallyBasedMaterial = new PhysicallyBasedMaterial();

                    foreach (var oneTextureFile in _textureFiles)
                    {
                        var textureType = oneTextureFile.Key;
                        var oneFileName = oneTextureFile.Value;

                        ShaderResourceView shaderResourceView;

                        if (!_texturesCache.TryGetValue(oneFileName, out shaderResourceView))
                        {
                            var convertTo32bppPRGBA = (textureType == TextureMapTypes.BaseColor ||
                                                       textureType == TextureMapTypes.Albedo ||
                                                       textureType == TextureMapTypes.DiffuseColor);

                            shaderResourceView = Ab3d.DirectX.TextureLoader.LoadShaderResourceView(MainDXViewportView.DXScene.DXDevice.Device, oneFileName, loadDdsIfPresent: false, convertTo32bppPRGBA: convertTo32bppPRGBA);

                            physicallyBasedMaterial.TextureMaps.Add(new TextureMapInfo((Ab3d.DirectX.Materials.TextureMapTypes)textureType, shaderResourceView, null, oneFileName));

                            _texturesCache.Add(oneFileName, shaderResourceView);
                        }
                    }

                    _dxMaterials.Add(assimpMaterial, physicallyBasedMaterial);
                    _disposables.Add(physicallyBasedMaterial);
                }
            }

            return(physicallyBasedMaterial);
        }
        private void AddPBRTextures(AssimpMaterial assimpMaterial, string filePath, string customTexturesFolder, bool useStrictFileNameMatch, bool supportDDSTextures, PhysicallyBasedMaterial physicallyBasedMaterial)
        {
            //PhysicallyBasedMaterial physicallyBasedMaterial;
            string diffuseTextureFileName = assimpMaterial.TextureDiffuse.FilePath;

            if (!string.IsNullOrEmpty(customTexturesFolder))
            {
                diffuseTextureFileName = System.IO.Path.Combine(customTexturesFolder, System.IO.Path.GetFileName(diffuseTextureFileName));
            }
            else if (!System.IO.Path.IsPathRooted(diffuseTextureFileName))
            {
                diffuseTextureFileName = System.IO.Path.Combine(filePath, diffuseTextureFileName);
            }

            string folderName = System.IO.Path.GetDirectoryName(diffuseTextureFileName);

            if (!System.IO.Directory.Exists(folderName))
            {
                Log($"  Folder for diffuse texture does not exist: {folderName ?? ""}:");
                return;
            }


            if (_folderImageFiles == null)
            {
                _folderImageFiles = new Dictionary <string, string[]>();
            }

            string[] allFilesInFolder;

            if (!_folderImageFiles.TryGetValue(folderName, out allFilesInFolder))
            {
                allFilesInFolder = System.IO.Directory.GetFiles(folderName, "*.*", SearchOption.TopDirectoryOnly);
                _folderImageFiles.Add(folderName, allFilesInFolder);
            }


            //TextureMapTypes textureMapType = KnownTextureFiles.GetTextureType(diffuseTextureFileName);

            string fileNameWithoutKnownSuffix = KnownTextureFiles.GetFileNameWithoutKnownSuffix(diffuseTextureFileName);

            // Get material files that start with the diffuse texture file name without a suffix
            List <string> materialFiles;

            if (useStrictFileNameMatch)
            {
                materialFiles = allFilesInFolder.Where(f => fileNameWithoutKnownSuffix == KnownTextureFiles.GetFileNameWithoutKnownSuffix(f)).ToList();
            }
            else
            {
                materialFiles = allFilesInFolder.Where(f => f.IndexOf(fileNameWithoutKnownSuffix, 0, StringComparison.OrdinalIgnoreCase) != -1).ToList();
            }


            _textureFiles.Clear();

            if (materialFiles.Count == 0)
            {
                Log($"   Folder ({folderName}) for {assimpMaterial.Name ?? ""} material does not define any texture files");
                return;
            }
            else
            {
                bool hasDiffuseTexture = false;
                foreach (var materialFile in materialFiles)
                {
                    if (!TextureLoader.IsSupportedFile(materialFile, supportDDSTextures)) // Skip unsupported files
                    {
                        continue;
                    }

                    var textureMapType = KnownTextureFiles.GetTextureType(materialFile);
                    if (textureMapType == TextureMapTypes.Unknown)
                    {
                        if (!hasDiffuseTexture)
                        {
                            textureMapType = TextureMapTypes.DiffuseColor; // First unknown file type is considered to be diffuse texture file
                        }
                        else
                        {
                            continue; // Unknown file type
                        }
                    }

                    bool isDiffuseTexture = (textureMapType == TextureMapTypes.DiffuseColor ||
                                             textureMapType == TextureMapTypes.Albedo ||
                                             textureMapType == TextureMapTypes.BaseColor);

                    string existingTextureFileName;
                    if (_textureFiles.TryGetValue(textureMapType, out existingTextureFileName))
                    {
                        // Map for this texture type already exist
                        var existingFileExtension = System.IO.Path.GetExtension(existingTextureFileName);
                        if (existingFileExtension != null && existingFileExtension.Equals(".dds", StringComparison.OrdinalIgnoreCase))
                        {
                            continue; // DDS texture already found for this texture type - we will use existing dds texture
                        }
                    }


                    hasDiffuseTexture |= isDiffuseTexture;

                    _textureFiles.Add(textureMapType, materialFile);

                    Log("    " + textureMapType + ": " + System.IO.Path.GetFileName(materialFile));
                }

                if (_textureFiles.Count > 0)
                {
                    foreach (var oneTextureFile in _textureFiles)
                    {
                        var textureType = oneTextureFile.Key;
                        var oneFileName = oneTextureFile.Value;

                        ShaderResourceView shaderResourceView;

                        if (!_texturesCache.TryGetValue(oneFileName, out shaderResourceView))
                        {
                            var isBaseColor = (textureType == TextureMapTypes.BaseColor ||
                                               textureType == TextureMapTypes.Albedo ||
                                               textureType == TextureMapTypes.DiffuseColor);

                            // 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;
                            shaderResourceView = Ab3d.DirectX.TextureLoader.LoadShaderResourceView(MainDXViewportView.DXScene.Device,
                                                                                                   oneFileName,
                                                                                                   loadDdsIfPresent: true,
                                                                                                   convertTo32bppPRGBA: isBaseColor,
                                                                                                   generateMipMaps: true,
                                                                                                   textureInfo: out textureInfo);

                            physicallyBasedMaterial.TextureMaps.Add(new TextureMapInfo((Ab3d.DirectX.Materials.TextureMapTypes)textureType, shaderResourceView, null, oneFileName));

                            if (isBaseColor)
                            {
                                // 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);

                                physicallyBasedMaterial.BlendState      = recommendedBlendState;
                                physicallyBasedMaterial.HasTransparency = textureInfo.HasTransparency;
                            }


                            _texturesCache.Add(oneFileName, shaderResourceView);
                        }
                    }
                }
            }
        }
        private void AddTextureMapSelections(string materialName, PhysicallyBasedMaterial physicallyBasedMaterial)
        {
            if (physicallyBasedMaterial == null)
            {
                return;
            }

            var expander = new Expander()
            {
                Header     = materialName,
                Margin     = new Thickness(0, 0, 0, 3),
                IsExpanded = true
            };

            TextureMapsPanel.Children.Add(expander);


            var stackPanel = new StackPanel()
            {
                Orientation = Orientation.Vertical
            };

            expander.Content = stackPanel;


            //if (!string.IsNullOrEmpty(materialName))
            //{
            //    var textBlock = new TextBlock()
            //    {
            //        Text       = materialName,
            //        FontWeight = FontWeights.Bold,
            //        Margin = new Thickness(0, 0, 0, 3)
            //    };

            //    TextureMapsPanel.Children.Add(textBlock);
            //}

            bool   hasDiffuseColor = physicallyBasedMaterial.HasTextureMap(TextureMapTypes.DiffuseColor);
            string baseFolder      = System.IO.Path.GetDirectoryName(_loadedFileName);

            foreach (var supportedTextureMapType in KnownTextureFiles.PBRSupportedTextureMapTypes)
            {
                // Show only one of DiffuseColor or BaseColor (not both)
                // Show DiffuseColor only if there is a texture map defined for it
                if ((supportedTextureMapType == TextureMapTypes.DiffuseColor && !hasDiffuseColor) ||
                    (supportedTextureMapType == TextureMapTypes.BaseColor && hasDiffuseColor))
                {
                    continue;
                }

                var textureMapSelectionControl = new TextureMapSelectionControl(physicallyBasedMaterial, supportedTextureMapType, baseFolder);
                textureMapSelectionControl.Margin = new Thickness(23, 0, 0, 7);

                textureMapSelectionControl.MapSettingsChanged += TextureMapSelectionControlOnMapSettingsChanged;
                textureMapSelectionControl.LayoutTransform     = new ScaleTransform(0.75, 0.75);

                if (MainDXViewportView.DXScene != null)
                {
                    textureMapSelectionControl.DXDevice = MainDXViewportView.DXScene.DXDevice;
                }

                //TextureMapsPanel.Children.Add(textureMapSelectionControl);
                stackPanel.Children.Add(textureMapSelectionControl);
            }
        }
Beispiel #6
0
        private void CreateSampleScene()
        {
            _physicallyBasedMaterial = new PhysicallyBasedMaterial();

            // We need to dispose the PhysicallyBasedMaterial when this sample is uloaded
            _disposables.Add(_physicallyBasedMaterial);


            UpdateBaseColor();
            UpdateMetalness();
            UpdateRoughness();

            var normalMapShaderResourceView = GetNormalMapShaderResourceView();

            if (normalMapShaderResourceView != null)
            {
                _physicallyBasedMaterial.SetTextureMap(TextureMapTypes.NormalMap, normalMapShaderResourceView, "bricks_normal.png");
            }

            var ambientOcclusionShaderResourceView = AmbientOcclusionShaderResourceView();

            if (ambientOcclusionShaderResourceView != null)
            {
                _physicallyBasedMaterial.SetTextureMap(TextureMapTypes.AmbientOcclusion, ambientOcclusionShaderResourceView, "bricks_ao.png");
            }



            var wpfMaterial = new DiffuseMaterial(Brushes.Red);

            wpfMaterial.SetUsedDXMaterial(_physicallyBasedMaterial);

            ModelPlaceholder.Content = null;
            ModelPlaceholder.Children.Clear();


            var sphereVisual3D = new Ab3d.Visuals.SphereVisual3D()
            {
                CenterPosition          = new Point3D(40, 12, 0),
                Radius                  = 12,
                Segments                = 50,
                Material                = wpfMaterial,
                FreezeMeshGeometry3D    = false,
                UseCachedMeshGeometry3D = false
            };

            ModelPlaceholder.Children.Add(sphereVisual3D);


            var boxVisual3D = new Ab3d.Visuals.BoxVisual3D()
            {
                CenterPosition          = new Point3D(-40, 10, 0),
                Size                    = new Size3D(20, 20, 20),
                Material                = wpfMaterial,
                FreezeMeshGeometry3D    = false,
                UseCachedMeshGeometry3D = false
            };

            ModelPlaceholder.Children.Add(boxVisual3D);


            var readerObj = new Ab3d.ReaderObj();

            var readModel3D = (GeometryModel3D)readerObj.ReadModel3D(_modelsFolder + "teapot-hires.obj");

            Ab3d.Utilities.ModelUtils.CenterAndScaleModel3D(readModel3D, new Point3D(0, 10, 0), new Size3D(40, 40, 40), true);

            //// This code is called for each GeometryModel3D inside Plane1
            //var tangentVectors = Ab3d.DirectX.Utilities.MeshUtils.CalculateTangentVectors((MeshGeometry3D)readModel3D.Geometry);

            ////// Assign tangent array to the MeshGeometry3D
            //readModel3D.Geometry.SetDXAttribute(DXAttributeType.MeshTangentArray, tangentVectors);



            readModel3D.Material = wpfMaterial;

            //ModelPlaceholder.Content = null;
            ModelPlaceholder.Children.Add(readModel3D.CreateModelVisual3D());



            // Rendering normal (bump) maps require tangent vectors.
            // The following code will generate tangent vectors and assign them to the MeshGeometry3D that form our 3D model.
            // If tangent vectors are not provided, they will be calculated on-demand in the pixel shader (slightly reducing performance).

            Ab3d.Utilities.ModelIterator.IterateGeometryModel3DObjects(ModelPlaceholder, delegate(GeometryModel3D geometryModel3D, Transform3D transform3D)
            {
                // This code is called for each GeometryModel3D inside Plane1
                var tangentVectors = Ab3d.DirectX.Utilities.MeshUtils.CalculateTangentVectors((MeshGeometry3D)geometryModel3D.Geometry);

                // Assign tangent array to the MeshGeometry3D
                geometryModel3D.Geometry.SetDXAttribute(DXAttributeType.MeshTangentArray, tangentVectors);
            });


            Camera1.Distance = 150;

            UpdateLights();
        }