mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3830 lines
178 KiB
3830 lines
178 KiB
#ifndef Magnum_Trade_MaterialData_h |
|
#define Magnum_Trade_MaterialData_h |
|
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
|
2020, 2021, 2022, 2023, 2024 |
|
Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a |
|
copy of this software and associated documentation files (the "Software"), |
|
to deal in the Software without restriction, including without limitation |
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
and/or sell copies of the Software, and to permit persons to whom the |
|
Software is furnished to do so, subject to the following conditions: |
|
|
|
The above copyright notice and this permission notice shall be included |
|
in all copies or substantial portions of the Software. |
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
DEALINGS IN THE SOFTWARE. |
|
*/ |
|
|
|
/** @file |
|
* @brief Class @ref Magnum::Trade::MaterialData, @ref Magnum::Trade::MaterialAttributeData, enum @ref Magnum::Trade::MaterialLayer, @ref Magnum::Trade::MaterialAttribute, @ref Magnum::Trade::MaterialTextureSwizzle, @ref Magnum::Trade::MaterialAttributeType |
|
* @m_since_latest |
|
*/ |
|
|
|
#include <Corrade/Containers/Array.h> |
|
#include <Corrade/Containers/EnumSet.h> |
|
#include <Corrade/Containers/Optional.h> |
|
#include <Corrade/Containers/StringView.h> |
|
#include <Corrade/Utility/Endianness.h> |
|
|
|
#include "Magnum/Magnum.h" |
|
#include "Magnum/Math/RectangularMatrix.h" |
|
#include "Magnum/Trade/Data.h" |
|
#include "Magnum/Trade/Trade.h" |
|
#include "Magnum/Trade/visibility.h" |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
#include <Corrade/Utility/Macros.h> |
|
#endif |
|
|
|
namespace Magnum { namespace Trade { |
|
|
|
/** |
|
@brief Material layer name |
|
@m_since_latest |
|
|
|
Convenience aliases to actual layer name strings. The alias is in the same form |
|
and capitalization --- so for example @ref MaterialLayer::ClearCoat is an alias |
|
for @cpp "ClearCoat" @ce. Each layer is expected to contain (a subset of) the |
|
@ref MaterialAttribute::LayerName, @ref MaterialAttribute::LayerFactor, |
|
@ref MaterialAttribute::LayerFactorTexture, |
|
@ref MaterialAttribute::LayerFactorTextureSwizzle, |
|
@ref MaterialAttribute::LayerFactorTextureMatrix, |
|
@ref MaterialAttribute::LayerFactorTextureCoordinates attributes in addition to |
|
what's specified for a particular named layer. |
|
@see @ref MaterialData, @ref MaterialData::layerName(), @ref MaterialLayerData, |
|
@ref materialLayerName() |
|
*/ |
|
enum class MaterialLayer: UnsignedInt { |
|
/* Zero used for an invalid value */ |
|
|
|
/** |
|
* Clear coat material layer. |
|
* |
|
* Expected to contain (a subset of) the |
|
* @ref MaterialAttribute::Roughness, |
|
* @ref MaterialAttribute::RoughnessTexture, |
|
* @ref MaterialAttribute::RoughnessTextureSwizzle, |
|
* @ref MaterialAttribute::RoughnessTextureMatrix, |
|
* @ref MaterialAttribute::RoughnessTextureCoordinates, |
|
* @ref MaterialAttribute::NormalTexture, |
|
* @ref MaterialAttribute::NormalTextureSwizzle, |
|
* @ref MaterialAttribute::NormalTextureMatrix and |
|
* @ref MaterialAttribute::NormalTextureCoordinates attributes. |
|
* @see @ref PbrClearCoatMaterialData |
|
*/ |
|
ClearCoat = 1, |
|
}; |
|
|
|
namespace Implementation { |
|
/* Compared to materialLayerName() below returns an empty string for |
|
invalid layers, used internally to provide better assertion messages */ |
|
MAGNUM_TRADE_EXPORT Containers::StringView materialLayerNameInternal(MaterialLayer layer); |
|
} |
|
|
|
/** |
|
@brief Material layer name as a string |
|
|
|
Expects that @p layer is a valid @ref MaterialLayer value. The returned view |
|
has both @relativeref{Corrade,Containers::StringViewFlag::Global} and |
|
@relativeref{Corrade::Containers::StringViewFlag,NullTerminated} set. |
|
*/ |
|
MAGNUM_TRADE_EXPORT Containers::StringView materialLayerName(MaterialLayer layer); |
|
|
|
/** |
|
@debugoperatorenum{MaterialLayer} |
|
@m_since_latest |
|
*/ |
|
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, MaterialLayer value); |
|
|
|
/** |
|
@brief Material attribute name |
|
@m_since_latest |
|
|
|
Convenience aliases to actual attribute name strings. In most cases the alias |
|
is in the same form and capitalization --- so for example |
|
@ref MaterialAttribute::DoubleSided is an alias for @cpp "DoubleSided" @ce, the |
|
only exception is @ref MaterialAttribute::LayerName which is |
|
@cpp " LayerName" @ce (with a space at the front). |
|
|
|
When this enum is used in @ref MaterialAttributeData constructors, the data are |
|
additionally checked for type compatibility. Other than that, there is no |
|
difference to the string variants. |
|
|
|
Each attribute value documents the default value that should be used if the |
|
attribute isn't present. Some attributes, such as `*Texture`, have no defaults |
|
--- in that case it means the material doesn't use given feature. |
|
@see @ref MaterialAttributeData, @ref MaterialData, |
|
@ref materialAttributeName() |
|
*/ |
|
enum class MaterialAttribute: UnsignedInt { |
|
/* Zero used for an invalid value */ |
|
|
|
/** |
|
* Layer name, @ref MaterialAttributeType::String. |
|
* |
|
* Unlike other attributes where string name matches the enum name, in this |
|
* case the corresponding string is @cpp " LayerName" @ce (with a space at |
|
* the front), done in order to have the layer name attribute appear first |
|
* in each layer and thus simplify layer implementation. |
|
* |
|
* Default value is an empty string. |
|
* @see @ref MaterialData::layerName() |
|
*/ |
|
LayerName = 1, |
|
|
|
/** |
|
* Alpha mask, @ref MaterialAttributeType::Float. |
|
* |
|
* If set together with @ref MaterialAttribute::AlphaBlend, blending is |
|
* preferred, however renderers can fall back to alpha-masked rendering. |
|
* Alpha values below this value are meant to be rendered as fully |
|
* transparent and alpha values above this value as fully opaque. |
|
* |
|
* Default value is @cpp 0.5f @ce. |
|
* @see @ref MaterialAlphaMode, @ref MaterialData::alphaMode(), |
|
* @ref MaterialData::alphaMask() |
|
*/ |
|
AlphaMask, |
|
|
|
/** |
|
* Alpha blending, @ref MaterialAttributeType::Bool. |
|
* |
|
* If @cpp true @ce, the material is expected to be rendered with blending |
|
* enabled and in correct depth order. If @cpp false @ce or not present, |
|
* the material should be treated as opaque. If set together with |
|
* @ref MaterialAttribute::AlphaMask, blending is preferred, however |
|
* renderers can fall back to alpha-masked rendering. |
|
* |
|
* Default value is @cpp false @ce. |
|
* @see @ref MaterialAlphaMode, @ref MaterialData::alphaMode() |
|
*/ |
|
AlphaBlend, |
|
|
|
/** |
|
* Double sided, @ref MaterialAttributeType::Bool. |
|
* |
|
* Default value is @cpp false @ce. |
|
* @see @ref MaterialData::isDoubleSided() |
|
*/ |
|
DoubleSided, |
|
|
|
/** |
|
* Ambient color for Phong materials, @ref MaterialAttributeType::Vector4. |
|
* |
|
* If @ref MaterialAttribute::AmbientTexture is present as well, these two |
|
* are multiplied together. |
|
* |
|
* Default value is @cpp 0x000000ff_srgbaf @ce if there's no |
|
* @ref MaterialAttribute::AmbientTexture and @cpp 0xffffffff_srgbaf @ce if |
|
* there is. |
|
* @see @ref PhongMaterialData::ambientColor() |
|
*/ |
|
AmbientColor, |
|
|
|
/** |
|
* Ambient texture index for Phong materials, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* If @ref MaterialAttribute::AmbientColor is present as well, these two |
|
* are multiplied together. |
|
* @see @ref PhongMaterialData::ambientTexture() |
|
*/ |
|
AmbientTexture, |
|
|
|
/** |
|
* Ambient texture transformation matrix for Phong materials, |
|
* @ref MaterialAttributeType::Matrix3x3. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureMatrix if both are |
|
* present. |
|
* |
|
* Default value is an identity matrix. |
|
* @see @ref PhongMaterialData::ambientTextureMatrix() |
|
*/ |
|
AmbientTextureMatrix, |
|
|
|
/** |
|
* Ambient texture coordinate set index for Phong materials, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureCoordinates if both |
|
* are present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PhongMaterialData::ambientTextureCoordinates() |
|
*/ |
|
AmbientTextureCoordinates, |
|
|
|
/** |
|
* Ambient texture array layer for Phong materials, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureLayer if both are |
|
* present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PhongMaterialData::ambientTextureLayer() |
|
*/ |
|
AmbientTextureLayer, |
|
|
|
/** |
|
* Diffuse color for Phong or PBR specular/glossiness materials, |
|
* @ref MaterialAttributeType::Vector4. |
|
* |
|
* If @ref MaterialAttribute::DiffuseTexture is present as well, these two |
|
* are multiplied together. |
|
* |
|
* Default value is @cpp 0xffffffff_srgbaf @ce. |
|
* @see @ref FlatMaterialData::color(), |
|
* @ref PhongMaterialData::diffuseColor(), |
|
* @ref PbrSpecularGlossinessMaterialData::diffuseColor() |
|
*/ |
|
DiffuseColor, |
|
|
|
/** |
|
* Diffuse texture index for Phong or PBR specular/glossiness materials, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* If @ref MaterialAttribute::DiffuseColor is present as well, these two |
|
* are multiplied together. |
|
* @see @ref FlatMaterialData::texture(), |
|
* @ref PhongMaterialData::diffuseTexture(), |
|
* @ref PbrSpecularGlossinessMaterialData::diffuseTexture() |
|
*/ |
|
DiffuseTexture, |
|
|
|
/** |
|
* Diffuse texture transformation matrix for Phong or PBR |
|
* specular/glossiness materials, @ref MaterialAttributeType::Matrix3x3. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureMatrix if both are |
|
* present. |
|
* |
|
* Default value is an identity matrix. |
|
* @see @ref FlatMaterialData::textureMatrix(), |
|
* @ref PhongMaterialData::diffuseTextureMatrix(), |
|
* @ref PbrSpecularGlossinessMaterialData::diffuseTextureMatrix() |
|
*/ |
|
DiffuseTextureMatrix, |
|
|
|
/** |
|
* Diffuse texture coordinate set index for Phong or PBR |
|
* specular/glossiness materials, @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureCoordinates if both |
|
* are present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref FlatMaterialData::textureCoordinates(), |
|
* @ref PhongMaterialData::diffuseTextureCoordinates(), |
|
* @ref PbrSpecularGlossinessMaterialData::diffuseTextureCoordinates() |
|
*/ |
|
DiffuseTextureCoordinates, |
|
|
|
/** |
|
* Diffuse texture array layer for Phong materials, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureLayer if both are |
|
* present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PhongMaterialData::diffuseTextureLayer() |
|
*/ |
|
DiffuseTextureLayer, |
|
|
|
/** |
|
* Specular color for Phong or PBR specular/glossiness materials, |
|
* @ref MaterialAttributeType::Vector4. Alpha is commonly zero to not |
|
* interfere with alpha-masked objects, non-zero alpha can be for example |
|
* used to render transparent material which are still expected to have |
|
* specular highlights such as glass or soap bubbles. |
|
* |
|
* If @ref MaterialAttribute::SpecularTexture or |
|
* @ref MaterialAttribute::SpecularGlossinessTexture is present as well, |
|
* these two are multiplied together. |
|
* |
|
* Default value is @cpp 0xffffff00_srgbaf @ce. |
|
* @see @ref PhongMaterialData::specularColor(), |
|
* @ref PbrSpecularGlossinessMaterialData::specularColor() |
|
*/ |
|
SpecularColor, |
|
|
|
/** |
|
* Specular texture index for Phong or PBR specular/glossiness materials, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* If @ref MaterialAttribute::SpecularColor is present as well, these two |
|
* are multiplied together. Can be alternatively supplied as a packed |
|
* @ref MaterialAttribute::SpecularGlossinessTexture. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PhongMaterialData::hasSpecularTexture(), |
|
* @ref PhongMaterialData::specularTexture(), |
|
* @ref PbrSpecularGlossinessMaterialData::hasSpecularTexture(), |
|
* @ref PbrSpecularGlossinessMaterialData::hasSpecularGlossinessTexture(), |
|
* @ref PbrSpecularGlossinessMaterialData::specularTexture() |
|
*/ |
|
SpecularTexture, |
|
|
|
/** |
|
* Specular texture swizzle for Phong or PBR specular/glossiness materials, |
|
* @ref MaterialAttributeType::TextureSwizzle. |
|
* |
|
* Can be used to describe whether the alpha channel of a |
|
* @ref MaterialAttribute::SpecularTexture is used or not. Either |
|
* @ref MaterialTextureSwizzle::RGBA or @ref MaterialTextureSwizzle::RGB |
|
* is expected. Does not apply to |
|
* @ref MaterialAttribute::SpecularGlossinessTexture --- in that case, |
|
* the specular texture is always three-channel, regardless of this |
|
* attribute. |
|
* |
|
* Default value is @ref MaterialTextureSwizzle::RGB. |
|
* @see @ref PbrSpecularGlossinessMaterialData::specularTextureSwizzle() |
|
*/ |
|
SpecularTextureSwizzle, |
|
|
|
/** |
|
* Specular texture transformation matrix for Phong or PBR |
|
* specular/glossiness materials, @ref MaterialAttributeType::Matrix3x3. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureMatrix if both are |
|
* present. |
|
* |
|
* Default value is an identity matrix. |
|
* @see @ref PhongMaterialData::specularTextureMatrix(), |
|
* @ref PbrSpecularGlossinessMaterialData::glossinessTextureMatrix() |
|
*/ |
|
SpecularTextureMatrix, |
|
|
|
/** |
|
* Specular texture coordinate set index for Phong or PBR |
|
* specular/glossiness materials, @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureCoordinates if both |
|
* are present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PhongMaterialData::specularTextureCoordinates(), |
|
* @ref PbrSpecularGlossinessMaterialData::specularTextureCoordinates() |
|
*/ |
|
SpecularTextureCoordinates, |
|
|
|
/** |
|
* Specular texture array layer for Phong materials, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureLayer if both are |
|
* present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PhongMaterialData::specularTextureLayer(), |
|
* @ref PbrSpecularGlossinessMaterialData::specularTextureLayer() |
|
*/ |
|
SpecularTextureLayer, |
|
|
|
/** |
|
* Shininess value for Phong materials, @ref MaterialAttributeType::Float. |
|
* |
|
* No default value is specified for this attribute. |
|
* @see @ref PhongMaterialData::shininess() |
|
*/ |
|
Shininess, |
|
|
|
/** |
|
* Base color for PBR metallic/roughness materials, |
|
* @ref MaterialAttributeType::Vector4. |
|
* |
|
* If @ref MaterialAttribute::BaseColorTexture is present as well, these |
|
* two are multiplied together. |
|
* |
|
* Default value is @cpp 0xffffffff_srgbaf @ce. |
|
* @see @ref FlatMaterialData::color(), |
|
* @ref PbrMetallicRoughnessMaterialData::baseColor() |
|
*/ |
|
BaseColor, |
|
|
|
/** |
|
* Base color texture index for PBR metallic/roughness materials, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* If @ref MaterialAttribute::BaseColor is present as well, these two are |
|
* multiplied together. |
|
* @see @ref FlatMaterialData::texture(), |
|
* @ref PbrMetallicRoughnessMaterialData::baseColorTexture() |
|
*/ |
|
BaseColorTexture, |
|
|
|
/** |
|
* Base color texture transformation matrix for PBR metallic/roughness |
|
* materials, @ref MaterialAttributeType::Matrix3x3. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureMatrix if both are |
|
* present. |
|
* |
|
* Default value is an identity matrix. |
|
* @see @ref FlatMaterialData::textureMatrix(), |
|
* @ref PbrMetallicRoughnessMaterialData::baseColorTextureMatrix() |
|
*/ |
|
BaseColorTextureMatrix, |
|
|
|
/** |
|
* Base color texture coordinate set index for PBR metallic/roughness |
|
* materials, @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureCoordinates if both |
|
* are present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref FlatMaterialData::textureCoordinates(), |
|
* @ref PbrMetallicRoughnessMaterialData::baseColorTextureCoordinates() |
|
*/ |
|
BaseColorTextureCoordinates, |
|
|
|
/** |
|
* Base color texture array layer for PBR metallic/roughness materials, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureLayer if both are |
|
* present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref FlatMaterialData::textureLayer(), |
|
* @ref PbrMetallicRoughnessMaterialData::baseColorTextureLayer() |
|
*/ |
|
BaseColorTextureLayer, |
|
|
|
/** |
|
* Metalness for PBR metallic/roughness materials, |
|
* @ref MaterialAttributeType::Float. |
|
* |
|
* If @ref MaterialAttribute::MetalnessTexture or |
|
* @ref MaterialAttribute::NoneRoughnessMetallicTexture is present as well, |
|
* these two are multiplied together. |
|
* |
|
* Default value is @cpp 1.0f @ce. |
|
* @see @ref PbrMetallicRoughnessMaterialData::metalness() |
|
*/ |
|
Metalness, |
|
|
|
/** |
|
* Metalness texture index for PBR metallic/roughness materials, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* If @ref MaterialAttribute::Metalness is present as well, these two are |
|
* multiplied together. Can be alternatively supplied as a packed |
|
* @ref MaterialAttribute::NoneRoughnessMetallicTexture. |
|
* @see @ref PbrMetallicRoughnessMaterialData::hasMetalnessTexture(), |
|
* @ref PbrMetallicRoughnessMaterialData::hasNoneRoughnessMetallicTexture(), |
|
* @ref PbrMetallicRoughnessMaterialData::hasOcclusionRoughnessMetallicTexture(), |
|
* @ref PbrMetallicRoughnessMaterialData::hasNormalRoughnessMetallicTexture() |
|
* @ref PbrMetallicRoughnessMaterialData::metalnessTexture() |
|
*/ |
|
MetalnessTexture, |
|
|
|
/** |
|
* Metalness texture swizzle for PBR metallic/roughness materials, |
|
* @ref MaterialAttributeType::TextureSwizzle. |
|
* |
|
* Can be used to express arbitrary packing of |
|
* @ref MaterialAttribute::MetalnessTexture together with other maps in a |
|
* single texture. A single-channel swizzle value is expected. Does not |
|
* apply to @ref MaterialAttribute::NoneRoughnessMetallicTexture --- in |
|
* that case, the metalness is implicitly in the red channel regardless of |
|
* this attribute. |
|
* |
|
* Default value is @ref MaterialTextureSwizzle::R. |
|
* @see @ref PbrMetallicRoughnessMaterialData::hasNoneRoughnessMetallicTexture(), |
|
* @ref PbrMetallicRoughnessMaterialData::hasOcclusionRoughnessMetallicTexture(), |
|
* @ref PbrMetallicRoughnessMaterialData::hasNormalRoughnessMetallicTexture() |
|
* @ref PbrMetallicRoughnessMaterialData::metalnessTextureSwizzle() |
|
*/ |
|
MetalnessTextureSwizzle, |
|
|
|
/** |
|
* Metalness texture transformation matrix for PBR metallic/roughness |
|
* materials, @ref MaterialAttributeType::Matrix3x3. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureMatrix if both are |
|
* present. |
|
* |
|
* Default value is an identity matrix. |
|
* @see @ref PbrMetallicRoughnessMaterialData::metalnessTextureMatrix() |
|
*/ |
|
MetalnessTextureMatrix, |
|
|
|
/** |
|
* Metalness texture coordinate set index for PBR metallic/roughness |
|
* materials, @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureCoordinates if both |
|
* are present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PbrMetallicRoughnessMaterialData::metalnessTextureCoordinates() |
|
*/ |
|
MetalnessTextureCoordinates, |
|
|
|
/** |
|
* Metalness texture array layer for PBR metallic/roughness materials, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureLayer if both are |
|
* present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PbrMetallicRoughnessMaterialData::metalnessTextureLayer() |
|
*/ |
|
MetalnessTextureLayer, |
|
|
|
/** |
|
* Roughness for PBR metallic/roughness materials, |
|
* @ref MaterialAttributeType::Float. |
|
* |
|
* If @ref MaterialAttribute::RoughnessTexture or |
|
* @ref MaterialAttribute::NoneRoughnessMetallicTexture is present as well, |
|
* these two are multiplied together. |
|
* |
|
* Default value is @cpp 1.0f @ce. |
|
* @see @ref PbrMetallicRoughnessMaterialData::roughness() |
|
*/ |
|
Roughness, |
|
|
|
/** |
|
* Roughness texture index for PBR metallic/roughness materials, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* If @ref MaterialAttribute::Roughness is present as well, these two are |
|
* multiplied together. Can be alternatively supplied as a packed |
|
* @ref MaterialAttribute::NoneRoughnessMetallicTexture. |
|
* @see @ref PbrMetallicRoughnessMaterialData::hasRoughnessTexture(), |
|
* @ref PbrMetallicRoughnessMaterialData::hasNoneRoughnessMetallicTexture(), |
|
* @ref PbrMetallicRoughnessMaterialData::hasOcclusionRoughnessMetallicTexture(), |
|
* @ref PbrMetallicRoughnessMaterialData::hasNormalRoughnessMetallicTexture() |
|
* @ref PbrMetallicRoughnessMaterialData::roughnessTexture() |
|
*/ |
|
RoughnessTexture, |
|
|
|
/** |
|
* Roughness texture swizzle for PBR metallic/roughness materials, |
|
* @ref MaterialAttributeType::TextureSwizzle. |
|
* |
|
* Can be used to express arbitrary packing of |
|
* @ref MaterialAttribute::RoughnessTexture together with other maps in a |
|
* single texture. A single-channel swizzle value is expected. Does not |
|
* apply to @ref MaterialAttribute::NoneRoughnessMetallicTexture --- in |
|
* that case, the metalness is implicitly in the green channel regardless |
|
* of this attribute. |
|
* |
|
* Default value is @ref MaterialTextureSwizzle::R. |
|
* @see @ref PbrMetallicRoughnessMaterialData::hasNoneRoughnessMetallicTexture(), |
|
* @ref PbrMetallicRoughnessMaterialData::hasOcclusionRoughnessMetallicTexture(), |
|
* @ref PbrMetallicRoughnessMaterialData::hasNormalRoughnessMetallicTexture() |
|
* @ref PbrMetallicRoughnessMaterialData::roughnessTextureSwizzle() |
|
*/ |
|
RoughnessTextureSwizzle, |
|
|
|
/** |
|
* Roughness texture transformation matrix for PBR metallic/roughness |
|
* materials, @ref MaterialAttributeType::Matrix3x3. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureMatrix if both are |
|
* present. |
|
* |
|
* Default value is an identity matrix. |
|
* @see @ref PbrMetallicRoughnessMaterialData::roughnessTextureMatrix() |
|
*/ |
|
RoughnessTextureMatrix, |
|
|
|
/** |
|
* Roughness texture coordinate set index for PBR metallic/roughness |
|
* materials, @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureCoordinates if both |
|
* are present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PbrMetallicRoughnessMaterialData::roughnessTextureCoordinates() |
|
*/ |
|
RoughnessTextureCoordinates, |
|
|
|
/** |
|
* Roughness texture array layer for PBR metallic/roughness materials, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureLayer if both are |
|
* present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PbrMetallicRoughnessMaterialData::roughnessTextureLayer() |
|
*/ |
|
RoughnessTextureLayer, |
|
|
|
/** |
|
* Combined roughness/metallic texture index for PBR metallic/roughness |
|
* materials with metalness in the blue channel and roughness in the green |
|
* channel, @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* If @ref MaterialAttribute::Metalness / @ref MaterialAttribute::Roughness |
|
* is present as well, these two are multiplied together. |
|
* |
|
* This is a convenience alias to simplify representation of glTF and UE4 |
|
* materials, which is where this packing is used ([rationale](https://github.com/KhronosGroup/glTF/issues/857)). |
|
* This packing (and other variants) can be alternatively specified as a |
|
* pair of @ref MaterialAttribute::RoughnessTexture / |
|
* @ref MaterialAttribute::MetalnessTexture attributes together with |
|
* @ref MaterialAttribute::RoughnessTextureSwizzle set to |
|
* @ref MaterialTextureSwizzle::G |
|
* and @ref MaterialAttribute::MetalnessTextureSwizzle set to |
|
* @ref MaterialTextureSwizzle::B. Texture transformation and coordinate |
|
* set, if needed, have to be specified either using the global |
|
* @ref MaterialAttribute::TextureMatrix and |
|
* @ref MaterialAttribute::TextureCoordinates attributes or the per-texture |
|
* @ref MaterialAttribute::RoughnessTextureMatrix, |
|
* @ref MaterialAttribute::MetalnessTextureMatrix, |
|
* @ref MaterialAttribute::RoughnessTextureCoordinates and |
|
* @ref MaterialAttribute::MetalnessTextureCoordinates variants. |
|
* @see @ref PbrMetallicRoughnessMaterialData::hasNoneRoughnessMetallicTexture(), |
|
* @ref PbrMetallicRoughnessMaterialData::hasOcclusionRoughnessMetallicTexture(), |
|
* @ref PbrMetallicRoughnessMaterialData::hasNormalRoughnessMetallicTexture() |
|
* @ref PbrMetallicRoughnessMaterialData::metalnessTexture(), |
|
* @ref PbrMetallicRoughnessMaterialData::roughnessTexture() |
|
*/ |
|
NoneRoughnessMetallicTexture, |
|
|
|
/* DiffuseColor, DiffuseTexture, DiffuseTextureMatrix, |
|
DiffuseTextureCoordinates, DiffuseTextureLayer, SpecularColor, |
|
SpecularTexture, SpecularTextureSwizzle, SpecularTextureMatrix, |
|
SpecularTextureCoordinates, SpecularTextureLayer specified above for |
|
Phong already */ |
|
|
|
/** |
|
* Glossiness for PBR specular/glossiness materials, |
|
* @ref MaterialAttributeType::Float. |
|
* |
|
* If @ref MaterialAttribute::GlossinessTexture or |
|
* @ref MaterialAttribute::SpecularGlossinessTexture is present as well, |
|
* these two are multiplied together. |
|
* |
|
* Default value is @cpp 1.0f @ce. |
|
* @see @ref PbrSpecularGlossinessMaterialData::glossiness() |
|
*/ |
|
Glossiness, |
|
|
|
/** |
|
* Glossiness texture index for PBR specular/glossiness materials, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* If @ref MaterialAttribute::Glossiness is present as well, these two are |
|
* multiplied together. Can be alternatively supplied as a packed |
|
* @ref MaterialAttribute::SpecularGlossinessTexture. |
|
* @see @ref PbrSpecularGlossinessMaterialData::hasGlossinessTexture(), |
|
* @ref PbrSpecularGlossinessMaterialData::hasSpecularGlossinessTexture(), |
|
* @ref PbrSpecularGlossinessMaterialData::glossinessTexture() |
|
*/ |
|
GlossinessTexture, |
|
|
|
/** |
|
* Glossiness texture swizzle for PBR specular/glossiness materials, |
|
* @ref MaterialAttributeType::TextureSwizzle. |
|
* |
|
* Can be used to express arbitrary packing of |
|
* @ref MaterialAttribute::GlossinessTexture together with other maps in a |
|
* single texture. A single-channel swizzle value is expected. Does not |
|
* apply to @ref MaterialAttribute::SpecularGlossinessTexture --- in that |
|
* case, the glossiness is implicitly in the alpha channel regardless of |
|
* this attribute. |
|
* |
|
* Default value is @ref MaterialTextureSwizzle::R. |
|
* @see @ref PbrSpecularGlossinessMaterialData::hasSpecularGlossinessTexture(), |
|
* @ref PbrSpecularGlossinessMaterialData::glossinessTextureSwizzle() |
|
*/ |
|
GlossinessTextureSwizzle, |
|
|
|
/** |
|
* Glossiness texture transformation matrix for PBR specular/glossiness |
|
* materials, @ref MaterialAttributeType::Matrix3x3. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureMatrix if both are |
|
* present. |
|
* |
|
* Default value is an identity matrix. |
|
* @see @ref PbrSpecularGlossinessMaterialData::glossinessTextureMatrix() |
|
*/ |
|
GlossinessTextureMatrix, |
|
|
|
/** |
|
* Glossiness texture coordinate set index for PBR specular/glossiness |
|
* materials, @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureCoordinates if both |
|
* are present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PbrSpecularGlossinessMaterialData::glossinessTextureCoordinates() |
|
*/ |
|
GlossinessTextureCoordinates, |
|
|
|
/** |
|
* Metalness texture array layer for PBR specular/glossiness materials, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureLayer if both are |
|
* present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PbrSpecularGlossinessMaterialData::glossinessTextureLayer() |
|
*/ |
|
GlossinessTextureLayer, |
|
|
|
/** |
|
* Combined specular/glossiness texture index for PBR specular/glossiness |
|
* materials with specular color in the RGB channels and glossiness in |
|
* alpha, @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* If @ref MaterialAttribute::SpecularColor / @ref MaterialAttribute::Glossiness |
|
* is present as well, these two are multiplied together. Can be |
|
* alternatively specified as a pair of @ref MaterialAttribute::SpecularTexture |
|
* / @ref MaterialAttribute::GlossinessTexture attributes together with |
|
* @ref MaterialAttribute::GlossinessTextureSwizzle set to |
|
* @ref MaterialTextureSwizzle::A. Texture transformation and coordinate |
|
* set, if needed, have to be specified either using the global |
|
* @ref MaterialAttribute::TextureMatrix and |
|
* @ref MaterialAttribute::TextureCoordinates attributes or the per-texture |
|
* @ref MaterialAttribute::SpecularTextureMatrix, |
|
* @ref MaterialAttribute::GlossinessTextureMatrix, |
|
* @ref MaterialAttribute::SpecularTextureCoordinates and |
|
* @ref MaterialAttribute::GlossinessTextureCoordinates variants. |
|
* @see @ref PbrSpecularGlossinessMaterialData::hasSpecularGlossinessTexture(), |
|
* @ref PbrSpecularGlossinessMaterialData::specularTexture(), |
|
* @ref PbrSpecularGlossinessMaterialData::glossinessTexture() |
|
*/ |
|
SpecularGlossinessTexture, |
|
|
|
/** |
|
* Tangent-space normal map texture index, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* If @ref MaterialAttribute::NormalTextureScale is present as well, these |
|
* two are multiplied together, affecting strength of the effect. The scale |
|
* @f$ s @f$ multiplies the XY channels of a normal @f$ \boldsymbol{n}' @f$ |
|
* fetched from (usually) an unsigned normal texture |
|
* @f$ \boldsymbol{t}_n @f$. The result is renormalized again after to form |
|
* the final normal @f$ \boldsymbol{n} @f$: @f[ |
|
* \begin{array}{rcl} |
|
* \boldsymbol{n}' & = & (2 \boldsymbol{t}_n - \boldsymbol{1}) (s, s, 1)^T \\ |
|
* \boldsymbol{n}\phantom{'} & = & \frac{\boldsymbol{n}'}{|\boldsymbol{n}'|} |
|
* \end{array} |
|
* @f] |
|
* |
|
* @see @ref PhongMaterialData::normalTexture(), |
|
* @ref PbrMetallicRoughnessMaterialData::hasNormalRoughnessMetallicTexture(), |
|
* @ref PbrMetallicRoughnessMaterialData::normalTexture(), |
|
* @ref PbrSpecularGlossinessMaterialData::normalTexture() |
|
*/ |
|
NormalTexture, |
|
|
|
/** |
|
* Normal texture scale, @ref MaterialAttributeType::Float. |
|
* |
|
* Scales the texture defined by @ref MaterialAttribute::NormalTexture, see |
|
* above for details. |
|
* |
|
* Default value is @cpp 1.0f @ce. |
|
* @see @ref PhongMaterialData::normalTextureScale(), |
|
* @ref PbrMetallicRoughnessMaterialData::normalTextureScale(), |
|
* @ref PbrSpecularGlossinessMaterialData::normalTextureScale(), |
|
* @ref PbrClearCoatMaterialData::normalTextureScale() |
|
*/ |
|
NormalTextureScale, |
|
|
|
/** |
|
* Normal texture swizzle, @ref MaterialAttributeType::TextureSwizzle. |
|
* |
|
* Can be used to express arbitrary packing together with other maps in a |
|
* single texture. A two- or three-channel swizzle value is expected. |
|
* |
|
* If the texture is just two-component, the remaining component is |
|
* implicit and calculated as @f$ z = \sqrt{1 - x^2 - y^2} @f$. In order to |
|
* account for numeric issues and avoid negative values under the square |
|
* root, it's commonly done as @f$ z = \sqrt{\max(0, 1 - x^2 - y^2)} @f$. |
|
* Additionally, to mitigate artifacts when storing normal texture in a |
|
* compressed format, @ref MaterialTextureSwizzle::GA may get used instead |
|
* of @ref MaterialTextureSwizzle::RG. |
|
* |
|
* Shader code that is able to reconstruct a XYZ normal from both RG and GA |
|
* variants assuming constant values in other channels ([source](https://github.com/KhronosGroup/glTF/issues/1682#issuecomment-557880407)): |
|
* |
|
* @snippet Trade.glsl unpackTwoChannelNormal |
|
* |
|
* Default value is @ref MaterialTextureSwizzle::RGB. |
|
* @see @ref PbrMetallicRoughnessMaterialData::hasNormalRoughnessMetallicTexture(), |
|
* @ref PbrMetallicRoughnessMaterialData::normalTextureSwizzle(), |
|
* @ref PbrSpecularGlossinessMaterialData::normalTextureSwizzle(), |
|
* @ref materialTextureSwizzleComponentCount() |
|
*/ |
|
NormalTextureSwizzle, |
|
|
|
/** |
|
* Normal texture transformation matrix, |
|
* @ref MaterialAttributeType::Matrix3x3. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureMatrix if both are |
|
* present. |
|
* |
|
* Default value is an identity matrix. |
|
* @see @ref PhongMaterialData::normalTextureMatrix(), |
|
* @ref PbrMetallicRoughnessMaterialData::normalTextureMatrix(), |
|
* @ref PbrSpecularGlossinessMaterialData::normalTextureMatrix() |
|
*/ |
|
NormalTextureMatrix, |
|
|
|
/** |
|
* Normal texture coordinate set index, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureCoordinates if both |
|
* are present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PhongMaterialData::normalTextureCoordinates(), |
|
* @ref PbrMetallicRoughnessMaterialData::normalTextureCoordinates(), |
|
* @ref PbrSpecularGlossinessMaterialData::normalTextureCoordinates() |
|
*/ |
|
NormalTextureCoordinates, |
|
|
|
/** |
|
* Normal texture array layer, @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureLayer if both are |
|
* present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PhongMaterialData::normalTextureLayer(), |
|
* @ref PbrMetallicRoughnessMaterialData::normalTextureLayer(), |
|
* @ref PbrSpecularGlossinessMaterialData::normalTextureLayer() |
|
*/ |
|
NormalTextureLayer, |
|
|
|
/** |
|
* Occlusion texture index, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Single-channel texture that multiplies the resulting material color |
|
* @f$ \boldsymbol{c} @f$: @f[ |
|
* \boldsymbol{c}_o = o \boldsymbol{c} |
|
* @f] |
|
* |
|
* If @ref MaterialAttribute::OcclusionTextureStrength is present as well, |
|
* it's used as an interpolation factor @f$ \color{m-success} s @f$ between |
|
* material color @f$ \boldsymbol{c} @f$ and color with occlusion applied |
|
* @f$ o \boldsymbol{c} @f$: @f[ |
|
* \boldsymbol{c}_o = \operatorname{lerp}(\boldsymbol{c}, o \boldsymbol{c}, {\color{m-success} s}) = |
|
* \boldsymbol{c} (1 - {\color{m-success} s}) + o \boldsymbol{c} {\color{m-success} s} |
|
* @f] |
|
* @see @ref PbrMetallicRoughnessMaterialData::hasOcclusionRoughnessMetallicTexture(), |
|
* @ref PbrMetallicRoughnessMaterialData::occlusionTexture(), |
|
* @ref PbrSpecularGlossinessMaterialData::occlusionTexture(), |
|
* @ref Math::lerp() |
|
*/ |
|
OcclusionTexture, |
|
|
|
/** |
|
* Occlusion texture strength, @ref MaterialAttributeType::Float. |
|
* |
|
* Affects the texture defined by @ref MaterialAttribute::OcclusionTexture, |
|
* see above for details. |
|
* |
|
* Default value is @cpp 1.0f @ce. |
|
* @see @ref PbrMetallicRoughnessMaterialData::occlusionTextureStrength(), |
|
* @ref PbrSpecularGlossinessMaterialData::occlusionTextureStrength() |
|
*/ |
|
OcclusionTextureStrength, |
|
|
|
/** |
|
* Occlusion texture swizzle, @ref MaterialAttributeType::TextureSwizzle. |
|
* |
|
* Can be used to express arbitrary packing together with other maps in a |
|
* single texture. A single-channel swizzle value is expected. |
|
* |
|
* Default value is @ref MaterialTextureSwizzle::R. |
|
* @see @ref PbrMetallicRoughnessMaterialData::hasOcclusionRoughnessMetallicTexture(), |
|
* @ref PbrMetallicRoughnessMaterialData::occlusionTextureSwizzle(), |
|
* @ref PbrSpecularGlossinessMaterialData::occlusionTextureSwizzle() |
|
*/ |
|
OcclusionTextureSwizzle, |
|
|
|
/** |
|
* Occlusion texture transformation matrix, |
|
* @ref MaterialAttributeType::Matrix3x3. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureMatrix if both are |
|
* present. |
|
* |
|
* Default value is an identity matrix. |
|
* @see @ref PbrMetallicRoughnessMaterialData::occlusionTextureMatrix(), |
|
* @ref PbrSpecularGlossinessMaterialData::occlusionTextureSwizzle() |
|
*/ |
|
OcclusionTextureMatrix, |
|
|
|
/** |
|
* Occlusion texture coordinate set index, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureCoordinates if both |
|
* are present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PbrMetallicRoughnessMaterialData::occlusionTextureCoordinates(), |
|
* @ref PbrSpecularGlossinessMaterialData::occlusionTextureCoordinates() |
|
*/ |
|
OcclusionTextureCoordinates, |
|
|
|
/** |
|
* Occlusion texture array layer, @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureLayer if both are |
|
* present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PbrMetallicRoughnessMaterialData::occlusionTextureLayer(), |
|
* @ref PbrSpecularGlossinessMaterialData::occlusionTextureLayer() |
|
*/ |
|
OcclusionTextureLayer, |
|
|
|
/** |
|
* Emissive color, |
|
* @ref MaterialAttributeType::Vector3. |
|
* |
|
* If @ref MaterialAttribute::EmissiveTexture is present as well, these two |
|
* are multiplied together. |
|
* |
|
* Default value is @cpp 0x000000_srgbf @ce. |
|
* @see @ref PbrMetallicRoughnessMaterialData::emissiveColor(), |
|
* @ref PbrSpecularGlossinessMaterialData::emissiveColor() |
|
*/ |
|
EmissiveColor, |
|
|
|
/** |
|
* Emissive texture index, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* If @ref MaterialAttribute::EmissiveColor is present as well, these two |
|
* are multiplied together. |
|
* @see @ref PbrMetallicRoughnessMaterialData::emissiveTexture(), |
|
* @ref PbrSpecularGlossinessMaterialData::emissiveTexture() |
|
*/ |
|
EmissiveTexture, |
|
|
|
/** @todo EmissiveTextureSwizzle? It's a color and I'm not aware of any |
|
existing packing schemes, so probably safe to assume it's always RGB */ |
|
|
|
/** |
|
* Emissive texture transformation matrix, |
|
* @ref MaterialAttributeType::Matrix3x3. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureMatrix if both are |
|
* present. |
|
* |
|
* Default value is an identity matrix. |
|
* @see @ref PbrMetallicRoughnessMaterialData::emissiveTextureMatrix(), |
|
* @ref PbrSpecularGlossinessMaterialData::emissiveTextureMatrix(), |
|
*/ |
|
EmissiveTextureMatrix, |
|
|
|
/** |
|
* Emissive texture coordinate set index, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureCoordinates if both |
|
* are present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PbrMetallicRoughnessMaterialData::emissiveTextureCoordinates(), |
|
* @ref PbrSpecularGlossinessMaterialData::emissiveTextureCoordinates() |
|
*/ |
|
EmissiveTextureCoordinates, |
|
|
|
/** |
|
* Emissive texture array layer, @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Has a precedence over @ref MaterialAttribute::TextureLayer if both are |
|
* present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PbrMetallicRoughnessMaterialData::emissiveTextureLayer(), |
|
* @ref PbrSpecularGlossinessMaterialData::emissiveTextureLayer() |
|
*/ |
|
EmissiveTextureLayer, |
|
|
|
/** |
|
* Layer intensity. @ref MaterialAttributeType::Float. |
|
* |
|
* Expected to be contained in additional layers, not the base material. |
|
* The exact semantic of this attribute is layer-specific. If |
|
* @ref MaterialAttribute::LayerFactorTexture is present as well, these two |
|
* are multiplied together. |
|
* |
|
* Default value is @cpp 1.0f @ce. |
|
* @see @ref MaterialData::layerFactor() |
|
*/ |
|
LayerFactor, |
|
|
|
/** |
|
* Layer intensity texture, @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Expected to be contained in additional layers, not the base material. |
|
* The exact semantic of this attribute is layer-specific. If |
|
* @ref MaterialAttribute::LayerFactor is present as well, these two are |
|
* multiplied together. |
|
* @see @ref MaterialData::layerFactorTexture() |
|
*/ |
|
LayerFactorTexture, |
|
|
|
/** |
|
* Layer intensity texture swizzle, @ref MaterialAttributeType::TextureSwizzle. |
|
* |
|
* Can be used to express arbitrary packing together with other maps in a |
|
* single texture. A single-channel swizzle value is expected. |
|
* |
|
* Default value is @ref MaterialTextureSwizzle::R. |
|
* @see @ref MaterialData::layerFactorTextureSwizzle() |
|
*/ |
|
LayerFactorTextureSwizzle, |
|
|
|
/** |
|
* Layer intensity texture transformation matrix, |
|
* @ref MaterialAttributeType::Matrix3x3. |
|
* |
|
* Expected to be contained in additional layers, not the base material. |
|
* Has a precedence over @ref MaterialAttribute::TextureMatrix if both are |
|
* present. |
|
* |
|
* Default value is an identity matrix. |
|
* @see @ref MaterialData::layerFactorTextureMatrix() |
|
*/ |
|
LayerFactorTextureMatrix, |
|
|
|
/** |
|
* Layer intensity texture coordinate set index, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Expected to be contained in additional layers, not the base material. |
|
* Has a precedence over @ref MaterialAttribute::TextureCoordinates if both |
|
* are present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref MaterialData::layerFactorTextureCoordinates() |
|
*/ |
|
LayerFactorTextureCoordinates, |
|
|
|
/** |
|
* Layer intensity texture array layer, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* Expected to be contained in additional layers, not the base material. |
|
* Has a precedence over @ref MaterialAttribute::TextureLayer if both are |
|
* present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref MaterialData::layerFactorTextureLayer() |
|
*/ |
|
LayerFactorTextureLayer, |
|
|
|
/** |
|
* Common texture transformation matrix for all textures, |
|
* @ref MaterialAttributeType::Matrix3x3. |
|
* |
|
* @ref MaterialAttribute::AmbientTextureMatrix / |
|
* @ref MaterialAttribute::DiffuseTextureMatrix / |
|
* @ref MaterialAttribute::SpecularTextureMatrix / |
|
* @ref MaterialAttribute::MetalnessTextureMatrix / |
|
* @ref MaterialAttribute::RoughnessTextureMatrix / |
|
* @ref MaterialAttribute::GlossinessTextureMatrix / |
|
* @ref MaterialAttribute::NormalTextureMatrix / |
|
* @ref MaterialAttribute::OcclusionTextureMatrix / |
|
* @ref MaterialAttribute::EmissiveTextureMatrix / |
|
* @ref MaterialAttribute::LayerFactorTextureMatrix have a precedence over |
|
* this attribute for given texture, if present. |
|
* |
|
* Default value is an identity matrix. |
|
* @see @ref PhongMaterialData::hasCommonTextureTransformation(), |
|
* @ref PbrMetallicRoughnessMaterialData::hasCommonTextureTransformation(), |
|
* @ref PbrSpecularGlossinessMaterialData::hasCommonTextureTransformation(), |
|
* @ref PbrClearCoatMaterialData::hasCommonTextureTransformation(), |
|
* @ref PhongMaterialData::commonTextureMatrix(), |
|
* @ref PbrMetallicRoughnessMaterialData::commonTextureMatrix(), |
|
* @ref PbrSpecularGlossinessMaterialData::commonTextureMatrix(), |
|
* @ref PbrClearCoatMaterialData::commonTextureMatrix(), |
|
* @ref FlatMaterialData::textureMatrix() |
|
*/ |
|
TextureMatrix, |
|
|
|
/** |
|
* Common texture coordinate set index for all textures, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* @ref MaterialAttribute::AmbientTextureCoordinates / |
|
* @ref MaterialAttribute::DiffuseTextureCoordinates / |
|
* @ref MaterialAttribute::SpecularTextureCoordinates / |
|
* @ref MaterialAttribute::MetalnessTextureCoordinates / |
|
* @ref MaterialAttribute::RoughnessTextureCoordinates / |
|
* @ref MaterialAttribute::GlossinessTextureCoordinates / |
|
* @ref MaterialAttribute::NormalTextureCoordinates / |
|
* @ref MaterialAttribute::OcclusionTextureCoordinates / |
|
* @ref MaterialAttribute::EmissiveTextureCoordinates / |
|
* @ref MaterialAttribute::LayerFactorTextureCoordinates have a precedence |
|
* over this attribute for given texture, if present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PhongMaterialData::hasCommonTextureCoordinates(), |
|
* @ref PbrMetallicRoughnessMaterialData::hasCommonTextureCoordinates(), |
|
* @ref PbrSpecularGlossinessMaterialData::hasCommonTextureCoordinates(), |
|
* @ref PbrClearCoatMaterialData::hasCommonTextureCoordinates(), |
|
* @ref PhongMaterialData::commonTextureCoordinates(), |
|
* @ref PbrMetallicRoughnessMaterialData::commonTextureCoordinates(), |
|
* @ref PbrSpecularGlossinessMaterialData::commonTextureCoordinates(), |
|
* @ref PbrClearCoatMaterialData::commonTextureCoordinates(), |
|
* @ref FlatMaterialData::textureCoordinates() |
|
*/ |
|
TextureCoordinates, |
|
|
|
/** |
|
* Common texture array layer for all textures, |
|
* @ref MaterialAttributeType::UnsignedInt. |
|
* |
|
* @ref MaterialAttribute::AmbientTextureLayer / |
|
* @ref MaterialAttribute::DiffuseTextureLayer / |
|
* @ref MaterialAttribute::SpecularTextureLayer / |
|
* @ref MaterialAttribute::MetalnessTextureLayer / |
|
* @ref MaterialAttribute::RoughnessTextureLayer / |
|
* @ref MaterialAttribute::GlossinessTextureLayer / |
|
* @ref MaterialAttribute::NormalTextureLayer / |
|
* @ref MaterialAttribute::OcclusionTextureLayer / |
|
* @ref MaterialAttribute::EmissiveTextureLayer / |
|
* @ref MaterialAttribute::LayerFactorTextureLayer have a precedence over |
|
* this attribute for given texture, if present. |
|
* |
|
* Default value is @cpp 0u @ce. |
|
* @see @ref PhongMaterialData::hasCommonTextureLayer(), |
|
* @ref PbrMetallicRoughnessMaterialData::hasCommonTextureLayer(), |
|
* @ref PbrSpecularGlossinessMaterialData::hasCommonTextureLayer(), |
|
* @ref PbrClearCoatMaterialData::hasCommonTextureLayer(), |
|
* @ref PhongMaterialData::commonTextureLayer(), |
|
* @ref PbrMetallicRoughnessMaterialData::commonTextureLayer(), |
|
* @ref PbrSpecularGlossinessMaterialData::commonTextureLayer(), |
|
* @ref PbrClearCoatMaterialData::commonTextureLayer(), |
|
* @ref FlatMaterialData::textureLayer() |
|
*/ |
|
TextureLayer, |
|
}; |
|
|
|
namespace Implementation { |
|
/* Compared to materialLayerName() below returns an empty string for |
|
invalid layers, used internally to provide better assertion messages */ |
|
MAGNUM_TRADE_EXPORT Containers::StringView materialAttributeNameInternal(MaterialAttribute attribute); |
|
} |
|
|
|
/** |
|
@brief Material layer name as a string |
|
@m_since_latest |
|
|
|
Expects that @p attribute is a valid @ref MaterialAttribute value. The returned |
|
view has both @relativeref{Corrade,Containers::StringViewFlag::Global} and |
|
@relativeref{Corrade::Containers::StringViewFlag,NullTerminated} set. |
|
*/ |
|
MAGNUM_TRADE_EXPORT Containers::StringView materialAttributeName(MaterialAttribute attribute); |
|
|
|
/** |
|
@debugoperatorenum{MaterialAttribute} |
|
@m_since_latest |
|
*/ |
|
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, MaterialAttribute value); |
|
|
|
/** |
|
@brief Material texture swizzle |
|
@m_since_latest |
|
|
|
See @ref MaterialData for more information. |
|
@see @ref materialTextureSwizzleComponentCount() |
|
*/ |
|
enum class MaterialTextureSwizzle: UnsignedInt { |
|
/** Red component */ |
|
R = Utility::Endianness::fourCC('R', '\0', '\0', '\0'), |
|
|
|
/** Green component */ |
|
G = Utility::Endianness::fourCC('G', '\0', '\0', '\0'), |
|
|
|
/** Blue component */ |
|
B = Utility::Endianness::fourCC('B', '\0', '\0', '\0'), |
|
|
|
/** Alpha component */ |
|
A = Utility::Endianness::fourCC('A', '\0', '\0', '\0'), |
|
|
|
/** Red and green component */ |
|
RG = Utility::Endianness::fourCC('R', 'G', '\0', '\0'), |
|
|
|
/** Green and blue component */ |
|
GB = Utility::Endianness::fourCC('G', 'B', '\0', '\0'), |
|
|
|
/** |
|
* Green and alpha component. May get used to mitigate artifacts when |
|
* storing two independent channels (such as two-channel normal maps) in |
|
* compressed texture formats --- these commonly have separately compressed |
|
* RGB and alpha, with green channel having the most precision of the RGB |
|
* triplet. |
|
* @see @ref MaterialAttribute::NormalTextureSwizzle |
|
*/ |
|
GA = Utility::Endianness::fourCC('G', 'A', '\0', '\0'), |
|
|
|
/** Blue and alpha component */ |
|
BA = Utility::Endianness::fourCC('B', 'A', '\0', '\0'), |
|
|
|
/** RGB components */ |
|
RGB = Utility::Endianness::fourCC('R', 'G', 'B', '\0'), |
|
|
|
/** GBA components */ |
|
GBA = Utility::Endianness::fourCC('G', 'B', 'A', '\0'), |
|
|
|
/** RGBA components */ |
|
RGBA = Utility::Endianness::fourCC('R', 'G', 'B', 'A'), |
|
}; |
|
|
|
/** |
|
@brief Component count in a material texture swizzle |
|
@m_since_latest |
|
|
|
Returns for example @cpp 2 @ce for @ref MaterialTextureSwizzle::GA. |
|
*/ |
|
MAGNUM_TRADE_EXPORT UnsignedInt materialTextureSwizzleComponentCount(MaterialTextureSwizzle swizzle); |
|
|
|
/** |
|
@debugoperatorenum{MaterialTextureSwizzle} |
|
@m_since_latest |
|
*/ |
|
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, MaterialTextureSwizzle value); |
|
|
|
/** |
|
@brief Material attribute type |
|
@m_since_latest |
|
|
|
See @ref MaterialData for more information. |
|
@see @ref MaterialAttribute, @ref MaterialAttributeData, |
|
@ref materialAttributeTypeSize() |
|
*/ |
|
enum class MaterialAttributeType: UnsignedByte { |
|
/* Zero used for an invalid value */ |
|
|
|
Bool = 1, /**< @cpp bool @ce <b></b> */ |
|
|
|
Float, /**< @ref Magnum::Float "Float" */ |
|
Deg, /**< @ref Magnum::Deg "Deg" */ |
|
Rad, /**< @ref Magnum::Rad "Rad" */ |
|
UnsignedInt, /**< @ref Magnum::UnsignedInt "UnsignedInt" */ |
|
Int, /**< @ref Magnum::Int "Int" */ |
|
UnsignedLong, /**< @ref Magnum::UnsignedLong "UnsignedLong" */ |
|
Long, /**< @ref Magnum::Long "Long" */ |
|
|
|
Vector2, /**< @ref Magnum::Vector2 "Vector2" */ |
|
Vector2ui, /**< @ref Magnum::Vector2ui "Vector2ui" */ |
|
Vector2i, /**< @ref Magnum::Vector2i "Vector2i" */ |
|
|
|
Vector3, /**< @ref Magnum::Vector3 "Vector3" */ |
|
Vector3ui, /**< @ref Magnum::Vector3ui "Vector3ui" */ |
|
Vector3i, /**< @ref Magnum::Vector3i "Vector3i" */ |
|
|
|
Vector4, /**< @ref Magnum::Vector4 "Vector4" */ |
|
Vector4ui, /**< @ref Magnum::Vector4ui "Vector4ui" */ |
|
Vector4i, /**< @ref Magnum::Vector4i "Vector4i" */ |
|
|
|
Matrix2x2, /**< @ref Magnum::Matrix2x2 "Matrix2x2" */ |
|
Matrix2x3, /**< @ref Magnum::Matrix2x3 "Matrix2x3" */ |
|
Matrix2x4, /**< @ref Magnum::Matrix2x4 "Matrix2x4" */ |
|
|
|
Matrix3x2, /**< @ref Magnum::Matrix3x2 "Matrix3x2" */ |
|
Matrix3x3, /**< @ref Magnum::Matrix3x3 "Matrix3x3" */ |
|
Matrix3x4, /**< @ref Magnum::Matrix3x4 "Matrix3x4" */ |
|
|
|
Matrix4x2, /**< @ref Magnum::Matrix4x2 "Matrix4x2" */ |
|
Matrix4x3, /**< @ref Magnum::Matrix4x3 "Matrix4x3" */ |
|
|
|
/* Matrix4x4 not present as it won't fit (a deliberate decision), see |
|
MaterialData docs for more information */ |
|
|
|
/** |
|
* @cpp const void* @ce, type is not preserved. For convenience it's |
|
* possible to retrieve the value by calling @cpp attribute<const T*>() @ce |
|
* with an arbitrary `T` but the user has to ensure the type is correct. |
|
*/ |
|
Pointer, |
|
|
|
/** |
|
* @cpp void* @ce, type is not preserved. For convenience it's possible to |
|
* retrieve the value by calling @cpp attribute<T*>() @ce with an arbitrary |
|
* `T` but the user has to ensure the type is correct. |
|
*/ |
|
MutablePointer, |
|
|
|
/** |
|
* Null-terminated string. Can be stored using any type convertible to |
|
* @relativeref{Corrade,Containers::StringView}, retrieval has to be done |
|
* using @relativeref{Corrade,Containers::StringView}. |
|
*/ |
|
String, |
|
|
|
/** |
|
* Opaque data. Can be stored using any type convertible to |
|
* @relativeref{Corrade,Containers::ArrayView}, retrieval has to be done |
|
* using @ref Corrade::Containers::ArrayView "Containers::ArrayView<const void>". |
|
*/ |
|
Buffer, |
|
|
|
/** One of the values from @ref MaterialTextureSwizzle */ |
|
TextureSwizzle |
|
}; |
|
|
|
/** |
|
@brief Byte size of a material attribute type |
|
@m_since_latest |
|
|
|
Can't be used with @ref MaterialAttributeType::String, as the size varies |
|
depending on the value. |
|
*/ |
|
MAGNUM_TRADE_EXPORT std::size_t materialAttributeTypeSize(MaterialAttributeType type); |
|
|
|
/** |
|
@debugoperatorenum{MaterialAttributeType} |
|
@m_since_latest |
|
*/ |
|
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, MaterialAttributeType value); |
|
|
|
namespace Implementation { |
|
template<class> struct MaterialAttributeTypeFor; |
|
enum: std::size_t { MaterialAttributeDataSize = 64 }; |
|
} |
|
|
|
/** |
|
@brief Material attribute data |
|
@m_since_latest |
|
|
|
See @ref MaterialData for more information. |
|
*/ |
|
class MAGNUM_TRADE_EXPORT MaterialAttributeData { |
|
public: |
|
/** |
|
* @brief Default constructor |
|
* |
|
* Leaves contents at unspecified values. Provided as a convenience for |
|
* initialization of the attribute array for @ref MaterialData, |
|
* expected to be replaced with concrete values later. |
|
*/ |
|
constexpr explicit MaterialAttributeData() noexcept: _data{} {} |
|
|
|
/** |
|
* @brief Construct with a string name |
|
* @param name Attribute name |
|
* @param value Attribute value |
|
* |
|
* The @p name is expected to be non-empty and together with @p value |
|
* is expected to fit into 62 bytes. @ref MaterialAttributeType is |
|
* inferred from the type passed. |
|
* |
|
* This function is useful in @cpp constexpr @ce contexts and for |
|
* creating custom material attributes. For known attributes prefer to |
|
* use @ref MaterialAttributeData(MaterialAttribute, const T&) if you |
|
* don't need @cpp constexpr @ce, as it additionally checks that given |
|
* attribute has the expected type. |
|
*/ |
|
template<class T |
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
, class = typename std::enable_if<!std::is_convertible<const T&, Containers::StringView>::value && !std::is_convertible<const T&, Containers::ArrayView<const void>>::value>::type |
|
#endif |
|
> constexpr /*implicit*/ MaterialAttributeData(Containers::StringView name, const T& value) noexcept; |
|
|
|
/** |
|
* @brief Construct with a string name and a string value |
|
* @param name Attribute name |
|
* @param value Attribute value |
|
* |
|
* The @p name is expected to be non-empty and the combined length of |
|
* @p name and @p value is expected to fit into 60 bytes. Type is set |
|
* to @ref MaterialAttributeType::String. |
|
* |
|
* This function is useful in @cpp constexpr @ce contexts and for |
|
* creating custom material attributes. For known attributes prefer to |
|
* use @ref MaterialAttributeData(MaterialAttribute, Containers::StringView) |
|
* if you don't need @cpp constexpr @ce, as it additionally checks that |
|
* given attribute has the expected type. |
|
*/ |
|
constexpr /*implicit*/ MaterialAttributeData(Containers::StringView name, Containers::StringView value) noexcept; |
|
|
|
/** |
|
* @brief Construct with a string name and a buffer value |
|
* @param name Attribute name |
|
* @param value Attribute value |
|
* |
|
* The @p name is expected to be non-empty and the combined length of |
|
* @p name and @p value is expected to fit into 61 bytes. Type is set |
|
* to @ref MaterialAttributeType::Buffer. |
|
* |
|
* This function is useful for creating custom material attributes. |
|
* Currently there isn't any builtin @ref MaterialAttribute with a |
|
* buffer data type. |
|
*/ |
|
/*implicit*/ MaterialAttributeData(Containers::StringView name, Containers::ArrayView<const void> value) noexcept: MaterialAttributeData{name, MaterialAttributeType::Buffer, 0, &value} {} |
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
/* "Sure can't be constexpr" overloads to avoid going through the |
|
*insane* overload puzzle when not needed */ |
|
template<class T, class = typename std::enable_if<!std::is_convertible<const T&, Containers::StringView>::value && !std::is_convertible<const T&, Containers::ArrayView<const void>>::value>::type> /*implicit*/ MaterialAttributeData(const char* name, const T& value) noexcept: MaterialAttributeData{name, Implementation::MaterialAttributeTypeFor<T>::type(), sizeof(T), &value} {} |
|
/*implicit*/ MaterialAttributeData(const char* name, Containers::StringView value) noexcept: MaterialAttributeData{name, MaterialAttributeType::String, 0, &value} {} |
|
#endif |
|
|
|
/** |
|
* @brief Construct with a predefined name |
|
* @param name Attribute name |
|
* @param value Attribute value |
|
* |
|
* Compared to @ref MaterialAttributeData(Containers::StringView, const T&) |
|
* checks that the attribute is in expected type. The |
|
* @ref MaterialAttribute gets converted to a corresponding string |
|
* name. Apart from the type check, the following two instances are |
|
* equivalent: |
|
* |
|
* @snippet Trade.cpp MaterialAttributeData-name |
|
*/ |
|
template<class T |
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
, class = typename std::enable_if<!std::is_convertible<const T&, Containers::StringView>::value>::type |
|
#endif |
|
> /*implicit*/ MaterialAttributeData(MaterialAttribute name, const T& value) noexcept: MaterialAttributeData{name, Implementation::MaterialAttributeTypeFor<T>::type(), &value} {} |
|
|
|
/** |
|
* @brief Construct with a predefined name and a string value |
|
* @param name Attribute name |
|
* @param value Attribute value |
|
* |
|
* Compared to @ref MaterialAttributeData(Containers::StringView, Containers::StringView) |
|
* checks that the attribute is in expected type. The |
|
* @ref MaterialAttribute gets converted to a corresponding string |
|
* name. |
|
*/ |
|
/*implicit*/ MaterialAttributeData(MaterialAttribute name, Containers::StringView value) noexcept: MaterialAttributeData{name, MaterialAttributeType::String, &value} {} |
|
|
|
/* No MaterialAttributeData(MaterialAttribute, Containers::ArrayView<const void>) |
|
variant as there's no builtin MaterialAttributeType::Buffer |
|
attribute yet */ |
|
|
|
/** |
|
* @brief Construct from a type-erased value |
|
* @param name Attribute name |
|
* @param type Attribute type |
|
* @param value Type-erased value |
|
* |
|
* The @p name is expected to be non-empty. |
|
* |
|
* In case @p type is neither @ref MaterialAttributeType::String nor |
|
* @ref MaterialAttributeType::Buffer, copies a number of bytes |
|
* according to @ref materialAttributeTypeSize() from @p value. The |
|
* @p name together with @p value is expected to fit into 62 bytes. |
|
* Note that in case of a @ref MaterialAttributeType::Pointer or a |
|
* @ref MaterialAttributeType::MutablePointer, takes a |
|
* *pointer to a pointer*, not the pointer value itself. |
|
* |
|
* In case @p type is @ref MaterialAttributeType::String, @p value is |
|
* expected to point to a @relativeref{Corrade,Containers::StringView}. |
|
* The combined length of @p name and @p value strings is expected to |
|
* fit into 60 bytes. In case @p type is |
|
* @ref MaterialAttributeType::Buffer, @p value is expected to point to |
|
* a @relativeref{Corrade,Containers::ArrayView}. The combined length |
|
* of @p name and @p value views is expected to fit into 61 bytes. |
|
*/ |
|
/*implicit*/ MaterialAttributeData(Containers::StringView name, MaterialAttributeType type, const void* value) noexcept; |
|
|
|
/** |
|
* @brief Construct with a predefined name and a type-erased value |
|
* @param name Attribute name |
|
* @param type Attribute type |
|
* @param value Attribute value |
|
* |
|
* Compared to @ref MaterialAttributeData(Containers::StringView, MaterialAttributeType, const void*) |
|
* checks that the attribute is in expected type. The |
|
* @ref MaterialAttribute gets converted to a corresponding string |
|
* name. |
|
*/ |
|
/*implicit*/ MaterialAttributeData(MaterialAttribute name, MaterialAttributeType type, const void* value) noexcept; |
|
|
|
/** |
|
* @brief Construct a layer name attribute |
|
* @param layerName Material layer name |
|
* |
|
* Equivalent to calling @ref MaterialAttributeData(MaterialAttribute, Containers::StringView) |
|
* with @ref MaterialAttribute::LayerName and a string corresponding to |
|
* @p layerName. |
|
*/ |
|
/*implicit*/ MaterialAttributeData(MaterialLayer layerName) noexcept; |
|
|
|
/** @brief Attribute type */ |
|
MaterialAttributeType type() const { return _data.type; } |
|
|
|
/** |
|
* @brief Attribute name |
|
* |
|
* The returned view always has |
|
* @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} set. |
|
*/ |
|
Containers::StringView name() const { return _data.data + 1; } |
|
|
|
/** |
|
* @brief Type-erased attribute value |
|
* |
|
* Cast the pointer to a concrete type based on @ref type(). Note that |
|
* in case of a @ref MaterialAttributeType::Pointer or a |
|
* @ref MaterialAttributeType::MutablePointer, returns a |
|
* *pointer to a pointer*, not the pointer value itself. |
|
* |
|
* In case of a @ref MaterialAttributeType::String, returns a |
|
* null-terminated @cpp const char* @ce (not a pointer to |
|
* @relativeref{Corrade,Containers::StringView}). This doesn't preserve |
|
* the actual string size in case the string data contain @cpp '\0' @ce |
|
* bytes, thus prefer to use typed access in that case. |
|
* |
|
* In case of a @ref MaterialAttributeType::Buffer, returns a |
|
* pointer to the data with no size information. Prefer to use typed |
|
* access in that case. |
|
*/ |
|
const void* value() const; |
|
|
|
/** |
|
* @brief Attribute value |
|
* |
|
* Expects that @p T corresponds to @ref type(). |
|
*/ |
|
template<class T> T value() const; |
|
|
|
private: |
|
friend MaterialData; |
|
|
|
explicit MaterialAttributeData(Containers::StringView name, const MaterialAttributeType type, std::size_t typeSize, const void* value) noexcept; |
|
|
|
/* Most of this is needed only for the constexpr constructor (yay C++), |
|
the actual data layout is |
|
|
|
|------------------------- x B -----------------------| |
|
|
|
+--------+------- .. -----+-------- .. ---------------+ |
|
| type | name .. \0 | data | |
|
| 1 B | (x - n - 2) B | n B | |
|
+--------+------- .. -----+-------- .. --------+------+ |
|
| String | name .. \0 | data .. \0 | size | |
|
| 1 B | (x - n - 4) B | n B | 1 B | |
|
+--------+------- .. -----+-------- .. -------++------+ |
|
| Buffer | name \0 | size | .. \0 | data | |
|
| 1 B | m + 1 B | 1 B | (x - m - n - 3) B | n B | |
|
+--------+---------+------+-------- .. -------+-------+ |
|
|
|
where |
|
|
|
- `x` is Implementation::MaterialAttributeDataSize, |
|
- `type` is an 8-bit MaterialAttributeType, |
|
- `data` is of size matching `type`, at the offset of |
|
`(x - materialAttributeTypeSize(type))` B, or in case of strings |
|
at offset `(x - string.size() - 2)` B, with one byte for storing |
|
size and one null terminator, or in case of buffers at offset |
|
`(x - buffer.size())` B, |
|
- `name` is a null-terminated string filling the rest |
|
|
|
This way the name is always at the same offset to make binary search |
|
lookup fast and efficient, and data being at the end (instead of |
|
right after the null-terminated string) makes them accessible in O(1) |
|
as well. In case of string values, to achieve O(1) access, the size |
|
is stored as the last byte and the string data is right before. |
|
|
|
The only exception is arbitrary data buffers. There, similarly to |
|
plain values, it's important that the data are aligned, which means |
|
we can't store the 1-byte size at the end. Instead, it's put right |
|
after the null-terminated name, which means it takes O(m) to |
|
retrieve. But since names have a constant upper bound on their length |
|
and buffers are not so common, it shouldn't be too problematic. */ |
|
struct StringData { |
|
template<std::size_t ...sequence> constexpr explicit StringData(MaterialAttributeType type, Containers::StringView name, Containers::StringView value, Containers::Implementation::Sequence<sequence...>): type{type}, nameValue{(sequence < name.size() ? name[sequence] : (sequence - (Implementation::MaterialAttributeDataSize - value.size() - 3) < value.size() ? value[sequence - (Implementation::MaterialAttributeDataSize - value.size() - 3)] : '\0'))...}, size{UnsignedByte(value.size())} {} |
|
constexpr explicit StringData(MaterialAttributeType type, Containers::StringView name, Containers::StringView value): StringData{type, name, value, typename Containers::Implementation::GenerateSequence<Implementation::MaterialAttributeDataSize - 2>::Type{}} {} |
|
|
|
MaterialAttributeType type; |
|
char nameValue[Implementation::MaterialAttributeDataSize - 2]; |
|
UnsignedByte size; |
|
}; |
|
union ErasedScalar { |
|
constexpr explicit ErasedScalar(Float value): f{value} {} |
|
constexpr explicit ErasedScalar(Deg value): f{Float(value)} {} |
|
constexpr explicit ErasedScalar(Rad value): f{Float(value)} {} |
|
constexpr explicit ErasedScalar(UnsignedInt value): u{value} {} |
|
constexpr explicit ErasedScalar(Int value): i{value} {} |
|
constexpr explicit ErasedScalar(MaterialTextureSwizzle value): |
|
/* Interestingly enough, on GCC 4.8, using u{} will spam with |
|
warning: parameter ‘value’ set but not used [-Wunused-but-set-parameter] |
|
even though everything works as intended. Using () instead. */ |
|
u(UnsignedInt(value)) {} |
|
|
|
Float f; |
|
UnsignedInt u; |
|
Int i; |
|
}; |
|
union ErasedLongScalar { |
|
constexpr explicit ErasedLongScalar(UnsignedLong value): u{value} {} |
|
constexpr explicit ErasedLongScalar(Long value): i{value} {} |
|
|
|
UnsignedLong u; |
|
Long i; |
|
}; |
|
template<std::size_t size> union ErasedVector { |
|
constexpr explicit ErasedVector(const Math::Vector<size, Float>& value): f{value} {} |
|
constexpr explicit ErasedVector(const Math::Vector<size, UnsignedInt>& value): u{value} {} |
|
constexpr explicit ErasedVector(const Math::Vector<size, Int>& value): i{value} {} |
|
|
|
Math::Vector<size, Float> f; |
|
Math::Vector<size, UnsignedInt> u; |
|
Math::Vector<size, Int> i; |
|
}; |
|
template<std::size_t cols, std::size_t rows> union ErasedMatrix { |
|
constexpr explicit ErasedMatrix(const Math::RectangularMatrix<cols, rows, Float>& value): a{value} {} |
|
constexpr explicit ErasedMatrix(const Math::RectangularMatrix<rows, cols, Float>& value): b{value} {} |
|
|
|
Math::RectangularMatrix<cols, rows, Float> a; |
|
Math::RectangularMatrix<rows, cols, Float> b; |
|
}; |
|
template<class T> struct Data { |
|
template<class U, std::size_t ...sequence> constexpr explicit Data(MaterialAttributeType type, Containers::StringView name, const U& value, Containers::Implementation::Sequence<sequence...>): type{type}, name{(sequence < name.size() ? name[sequence] : '\0')...}, value{value} {} |
|
template<class U> constexpr explicit Data(MaterialAttributeType type, Containers::StringView name, const U& value): Data{type, name, value, typename Containers::Implementation::GenerateSequence<63 - sizeof(T)>::Type{}} {} |
|
|
|
MaterialAttributeType type; |
|
char name[Implementation::MaterialAttributeDataSize - sizeof(MaterialAttributeType) - sizeof(T)]; |
|
T value; |
|
}; |
|
union alignas(8) Storage { |
|
constexpr explicit Storage() noexcept: data{} {} |
|
|
|
constexpr explicit Storage(Containers::StringView name, Containers::StringView value) noexcept: s{MaterialAttributeType::String, name, value} {} |
|
|
|
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 1, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _1{type, name, value} {} |
|
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 4 && !std::is_pointer<T>::value, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _4{type, name, value} {} |
|
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 8 && !Math::IsVector<T>::value && !std::is_pointer<T>::value, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _8{type, name, value} {} |
|
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 8 && Math::IsVector<T>::value && !std::is_pointer<T>::value, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _8v{type, name, value} {} |
|
constexpr explicit Storage(MaterialAttributeType type, Containers::StringView name, const void* value) noexcept: p{type, name, value} {} |
|
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 12, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _12{type, name, value} {} |
|
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 16 && Math::IsVector<T>::value, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _16{type, name, value} {} |
|
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 16 && !Math::IsVector<T>::value, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _16m{type, name, value} {} |
|
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 24, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _24{type, name, value} {} |
|
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 32, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _32{type, name, value} {} |
|
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 36, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _36{type, name, value} {} |
|
template<class T> constexpr explicit Storage(typename std::enable_if<sizeof(T) == 48, MaterialAttributeType>::type type, Containers::StringView name, const T& value) noexcept: _48{type, name, value} {} |
|
|
|
MaterialAttributeType type; |
|
char data[Implementation::MaterialAttributeDataSize]; |
|
StringData s; |
|
/* Buffer values can't be filled in a constexpr way so they don't |
|
have a dedicated union type. The filling is done in |
|
MaterialAttributeData(Containers::StringView, MaterialAttributeType, std::size_t, const void*) |
|
manually instead. */ |
|
Data<bool> _1; |
|
Data<const void*> p; |
|
Data<ErasedScalar> _4; |
|
Data<ErasedLongScalar> _8; |
|
Data<ErasedVector<2>> _8v; |
|
Data<ErasedVector<3>> _12; |
|
Data<ErasedVector<4>> _16; |
|
Data<Math::RectangularMatrix<2, 2, Float>> _16m; |
|
Data<ErasedMatrix<2, 3>> _24; |
|
Data<ErasedMatrix<2, 4>> _32; |
|
Data<Math::RectangularMatrix<3, 3, Float>> _36; |
|
Data<ErasedMatrix<3, 4>> _48; |
|
} _data; |
|
|
|
static_assert(sizeof(Storage) == Implementation::MaterialAttributeDataSize, "something is off, huh"); |
|
}; |
|
|
|
/** |
|
@brief Material type |
|
|
|
@see @ref MaterialTypes, @ref MaterialData::types() |
|
*/ |
|
enum class MaterialType: UnsignedInt { |
|
/** |
|
* Flat. Use @ref FlatMaterialData for convenience attribute access. |
|
* Materials of this type are generally not combined with any other types. |
|
*/ |
|
Flat = 1 << 0, |
|
|
|
/** |
|
* Phong. Use @ref PhongMaterialData for convenience attribute access. |
|
*/ |
|
Phong = 1 << 1, |
|
|
|
/** |
|
* PBR metallic/roughness. Use @ref PbrMetallicRoughnessMaterialData for |
|
* convenience attribute access. |
|
*/ |
|
PbrMetallicRoughness = 1 << 2, |
|
|
|
/** |
|
* PBR specular/glossiness. Use @ref PbrSpecularGlossinessMaterialData for |
|
* convenience attribute access. |
|
*/ |
|
PbrSpecularGlossiness = 1 << 3, |
|
|
|
/** |
|
* PBR clear coat layer. Use @ref PbrClearCoatMaterialData for convenience |
|
* attribute access. |
|
*/ |
|
PbrClearCoat = 1 << 4 |
|
}; |
|
|
|
/** @debugoperatorenum{MaterialType} */ |
|
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, MaterialType value); |
|
|
|
/** |
|
@brief Material types |
|
@m_since_latest |
|
|
|
@see @ref MaterialData::types() |
|
*/ |
|
typedef Containers::EnumSet<MaterialType> MaterialTypes; |
|
|
|
CORRADE_ENUMSET_OPERATORS(MaterialTypes) |
|
|
|
/** @debugoperatorenum{MaterialTypes} */ |
|
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, MaterialTypes value); |
|
|
|
/** |
|
@brief Material alpha mode |
|
|
|
Convenience access to @ref MaterialAttribute::AlphaBlend and |
|
@ref MaterialAttribute::AlphaMask attributes. |
|
@see @ref MaterialData::alphaMode(), @ref MaterialData::alphaMask() |
|
*/ |
|
enum class MaterialAlphaMode: UnsignedByte { |
|
/** Alpha value is ignored and the rendered output is fully opaque. */ |
|
Opaque, |
|
|
|
/** |
|
* The rendered output is either fully transparent or fully opaque, |
|
* depending on the alpha value and specified |
|
* @ref MaterialData::alphaMask() value. |
|
*/ |
|
Mask, |
|
|
|
/** |
|
* The alpha value is used to combine source and destination colors using |
|
* additive blending. |
|
*/ |
|
Blend |
|
}; |
|
|
|
/** @debugoperatorenum{MaterialAlphaMode} */ |
|
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, MaterialAlphaMode value); |
|
|
|
/** |
|
@brief Material data |
|
@m_since_latest |
|
|
|
Key-value store for builtin as well as custom material attributes, with an |
|
ability to define additional layers further affecting the base material. |
|
Populated instances of this class are returned from |
|
@ref AbstractImporter::material(), can be passed to |
|
@ref AbstractSceneConverter::add(const MaterialData&, Containers::StringView) |
|
as well as used in various |
|
@ref MaterialTools algorithms |
|
. Like with other @ref Trade types, the internal |
|
representation is fixed upon construction and allows only optional in-place |
|
modification of the attribute values itself, but not of the overall structure. |
|
|
|
@section Trade-MaterialData-usage Usage |
|
|
|
The simplest usage is through templated @ref attribute() functions, which take |
|
a string attribute name or one of the pre-defined @ref MaterialAttribute |
|
values. You're expected to check for attribute presence first with |
|
@ref hasAttribute(), and the requested type has to match @ref attributeType(). |
|
To make things easier, each of the attributes defined in @ref MaterialAttribute |
|
has a strictly defined type, so you can safely assume the type when requesting |
|
those. In addition there's @ref findAttribute() and @ref attributeOr() that |
|
return a @relativeref{Corrade,Containers::NullOpt} or a default value in case |
|
given attribute is not found. |
|
|
|
@snippet Trade.cpp MaterialData-usage |
|
|
|
It's also possible to iterate through all attributes using @ref attributeName(), |
|
@ref attributeType() and @ref attribute() taking indices instead of names, with |
|
@ref attributeCount() returning the total attribute count. |
|
|
|
@subsection Trade-MaterialData-usage-types Material types and convenience accessors |
|
|
|
A material usually consists of a set of attributes for a particular rendering |
|
workflow --- PBR metallic/roughness, Phong or for example flat-shaded |
|
materials. To hint what the material contains, @ref types() returns a set of |
|
@ref MaterialType values. It's not just a single value as the data can define |
|
attributes for more than one material type (for example both metallic/roughness |
|
and specular/glossiness PBR workflow), allowing the application to pick the |
|
best type for a particular use case. |
|
|
|
Because retrieving everything through the @ref attribute() APIs can get verbose |
|
and complex, the @ref Trade library provides a set of accessor APIs for common |
|
material types such as @ref FlatMaterialData, @ref PhongMaterialData, |
|
@ref PbrMetallicRoughnessMaterialData, @ref PbrSpecularGlossinessMaterialData |
|
as well as material layers like @ref PbrClearCoatMaterialData. Using @ref as() |
|
you can convert any @ref MaterialData instance to a reference to one of those. |
|
These convenience APIs then take care of default values when an attribute isn't |
|
present or handle fallbacks when an attribute can be defined in multiple ways: |
|
|
|
@snippet Trade.cpp MaterialData-usage-types |
|
|
|
Each @ref MaterialAttribute is exposed through one or more of those convenience |
|
APIs, see the documentation of of a particular enum value for more information. |
|
|
|
@subsection Trade-MaterialData-usage-texture-complexity Texture packing, coordinate transformation and coordinate sets |
|
|
|
The material APIs allow for a lot of flexibility --- texture maps may be |
|
arbitrarily packed together to efficiently use all four channels, each texture |
|
can use a different set of texture coordinates and there can be a different |
|
coordinate transformation for each texture. |
|
|
|
In most cases, however, real-world textures fit into a few well-known packing |
|
schemes and usually have a common transformation and coordinate sets for all. |
|
Checking for all corner cases on the application side would be a headache, so |
|
there are queries like @ref PbrSpecularGlossinessMaterialData::hasSpecularGlossinessTexture() or |
|
@ref PbrSpecularGlossinessMaterialData::hasCommonTextureTransformation() to |
|
help narrowing the options down: |
|
|
|
@snippet Trade.cpp MaterialData-usage-texture-complexity |
|
|
|
@subsection Trade-MaterialData-usage-layers Material layers |
|
|
|
In addition to the base material, there can be material layers. While a |
|
material attribute can be specified only once for a particular layer, multiple |
|
layers can use the same attribute name for different purpose. Layers are |
|
commonly used in PBR workflows to describe lacquered wood, metallic paint or |
|
for example a thin film on leather surfaces. You can enumerate and query layers |
|
using @ref layerCount(), @ref layerName() and @ref hasLayer(), layer-specific |
|
attributes are retrieved by passing layer ID or name as the first parameter to |
|
the @ref attribute() family of APIs. |
|
|
|
For each layer there can be predefined @ref layerFactor(), |
|
@ref layerFactorTexture() and other texture-related attributes which define how |
|
much the layer affects the underlying material, but the exact semantics of how |
|
the factor is applied is left to the layer implementation. |
|
|
|
Here's an example showing retrieval of a clear coat layer parameters, if |
|
present: |
|
|
|
@snippet Trade.cpp MaterialData-usage-layers |
|
|
|
Like with base material attributes, builtin layers also have convenience |
|
accessor APIs. The above can be written in a more compact way using |
|
@link PbrClearCoatMaterialData @endlink: |
|
|
|
@snippet Trade.cpp MaterialData-usage-layers-types |
|
|
|
@subsection Trade-MaterialData-usage-mutable Mutable data access |
|
|
|
The interfaces implicitly return attribute values by copy or through |
|
@cpp const @ce views on the contained data through the @ref attributeData(), |
|
@ref layerData() and @ref attribute() accessors. This is done because in |
|
general case the data can also refer to a memory-mapped file or constant |
|
memory. In cases when it's desirable to modify the attribute values in-place, |
|
there's a set of @ref mutableAttribute() functions. To use these, you need to |
|
check that the data are mutable using @ref attributeDataFlags() first. The |
|
following snippet desaturates the base color of a PBR material: |
|
|
|
@snippet Trade.cpp MaterialData-usage-mutable |
|
|
|
Because the class internally expects the attribute data to be sorted and |
|
partitioned into layers, it's not possible to modify attribute names, |
|
add/remove attributes or change layer offsets --- only to edit values of |
|
existing attributes. |
|
|
|
@section Trade-MaterialData-populating Populating an instance |
|
|
|
A @ref MaterialData instance by default takes over ownership of an |
|
@relativeref{Corrade,Containers::Array} containing @ref MaterialAttributeData |
|
instances, together with @ref MaterialTypes suggesting available material types |
|
(or an empty set, in case of a fully custom material). Attribute values can be |
|
in one of the types from @ref MaterialAttributeType, and the type is in most |
|
cases inferred implicitly. The class internally uses strings for attribute |
|
names, but you're encouraged to use the predefined names from |
|
@ref MaterialAttribute --- with those, the attribute gets checked additionally |
|
that it's in an expected type. Attribute order doesn't matter, the array gets |
|
internally sorted by name to allow a @f$ \mathcal{O}(\log n) @f$ lookup. |
|
|
|
@snippet Trade.cpp MaterialData-populating |
|
|
|
@subsection Trade-MaterialData-populating-non-owned Non-owned instances |
|
|
|
In some cases you may want the @ref MaterialData instance to only refer to |
|
external data without taking ownership, for example with a memory-mapped file, |
|
global data etc. For that, instead of moving in an |
|
@relativeref{Corrade,Containers::Array} of @ref MaterialAttributeData or |
|
allocating it implicitly from an initializer list in the constructor, pass |
|
@ref DataFlags describing data mutability and ownership together with an |
|
@relativeref{Corrade,Containers::ArrayView}. Note that in this case, since the |
|
attribute data is treated as immutable, you *have to* ensure the list is |
|
already sorted by name. |
|
|
|
@snippet Trade.cpp MaterialData-populating-non-owned |
|
|
|
<b></b> |
|
|
|
@m_class{m-note m-info} |
|
|
|
@par |
|
Additionally, as shown above, in order to create a @cpp constexpr @ce |
|
@ref MaterialAttributeData array, you need to use |
|
@relativeref{Corrade,Containers::StringView} literals instead of plain C |
|
strings or the @ref MaterialAttribute enum, and be sure to call only |
|
@cpp constexpr @ce-enabled constructors of stored data types. |
|
|
|
@subsection Trade-MaterialData-populating-custom Custom material attributes |
|
|
|
While attribute names beginning with uppercase letters and whitespace are |
|
reserved for builtin Magnum attributes, anything beginning with a lowercase |
|
letter or a printable non-letter character can be a custom attribute. For |
|
greater flexibility, custom attributes can be also strings, untyped buffers |
|
or pointers, allowing you to store arbitrary properties such as image |
|
filenames or direct texture pointers instead of IDs: |
|
|
|
@snippet Trade.cpp MaterialData-populating-custom |
|
|
|
@subsection Trade-MaterialData-populating-layers Adding material layers |
|
|
|
Material layers are internally represented as ranges of the attribute array and |
|
by default the whole attribute array is treated as a base material. The actual |
|
split into layers can be described using an additional offset array passed to |
|
@ref MaterialData(MaterialTypes, Containers::Array<MaterialAttributeData>&&, Containers::Array<UnsignedInt>&&, const void*), |
|
where entry *i* specifies the end offset of layer *i* --- in the following |
|
snippet we have two layers (one base material and one clear coat layer), the |
|
base material being the first two attributes and the clear coat layer being |
|
attributes in range @cpp 2 @ce to @cpp 6 @ce (thus four attributes): |
|
|
|
@snippet Trade.cpp MaterialData-populating-layers |
|
|
|
Like with just a base material, the attributes get sorted for a |
|
@f$ \mathcal{O}(\log n) @f$ lookup --- but not as a whole, each layer |
|
separately. In contrary, because layer order matters, those are not reordered |
|
(and thus their lookup is @f$ \mathcal{O}(n) @f$, however it isn't expected to |
|
have that many layers for this to matter). The layers can be named by supplying |
|
a @ref MaterialAttribute::LayerName attribute (or, like shown above, by using |
|
the convenience @ref MaterialAttributeData::MaterialAttributeData(MaterialLayer) |
|
constructor) but don't have to --- if a layer doesn't have a name, it can be |
|
only looked up by its index, not by a name. |
|
|
|
Apart from builtin layers, there's no limit in what the layers can be used for |
|
--- the data can for example describe a completely custom landscape from a set |
|
of authored `rockTile`, `sandTile`, `grassTile` textures and procedurally |
|
generated blend factors `a`, `b`, `c`, `d`: |
|
|
|
@snippet Trade.cpp MaterialData-populating-layers-custom |
|
|
|
@section Trade-MaterialData-representation Internal representation |
|
|
|
The attributes are stored sorted by the key in a contiguous array, with each |
|
@ref MaterialAttributeData item occupying 64 bytes. The item contains a 1-byte |
|
type identifier, the actual value and the rest is occupied with null-terminated |
|
name. This means the name length can vary from 14 bytes for |
|
@ref Magnum::Matrix3x4 "Matrix3x4" / @ref Magnum::Matrix4x3 "Matrix4x3" to 61 |
|
bytes for @cpp bool @ce (excluding null terminator). As each item has a fixed |
|
size anyway, there's no value in supporting space-efficient 8-, 16- or |
|
half-float types. Conversely, @ref Magnum::Double "Double" types are currently |
|
not supported either as there isn't currently seen any need for extended |
|
precision. |
|
|
|
@m_class{m-block m-warning} |
|
|
|
@par Max representable data size |
|
With the current design, @ref MaterialAttributeData is 64 bytes and in |
|
order to fit a type identifier and a string attribute name of a reasonable |
|
length, the maximum data size is capped to 48 bytes. This means |
|
@ref Magnum::Matrix4x4 "Matrix4x4" isn't listed among supported types, but |
|
it shouldn't be a problem in practice --- ever an arbitrary color |
|
correction matrix is just 3x4 values with the bottom row being always |
|
@f$ \begin{pmatrix} 0 & 0 & 0 & 1 \end{pmatrix} @f$. This restriction might |
|
get lifted eventually. |
|
*/ |
|
class MAGNUM_TRADE_EXPORT MaterialData { |
|
public: |
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
/** |
|
* @brief Material flag |
|
* @m_deprecated_since_latest The flags are no longer stored directly |
|
* but generated on-the-fly from attribute data, which makes them |
|
* less efficient than calling @ref hasAttribute(), |
|
* @ref isDoubleSided() etc. |
|
* |
|
* This enum is further extended in subclasses. |
|
* @see @ref Flags, @ref flags() |
|
*/ |
|
enum class CORRADE_DEPRECATED_ENUM("use hasAttribute() etc. instead") Flag: UnsignedInt { |
|
/** |
|
* The material is double-sided. Back faces should not be culled |
|
* away but rendered as well, with normals flipped for correct |
|
* lighting. |
|
*/ |
|
DoubleSided = 1 << 0 |
|
}; |
|
|
|
/** |
|
* @brief Material flags |
|
* @m_deprecated_since_latest The flags are no longer stored directly |
|
* but generated on-the-fly from attribute data, which makes them |
|
* less efficient than calling @ref hasAttribute(), |
|
* @ref isDoubleSided() etc. |
|
* |
|
* This enum is extended in subclasses. |
|
* @see @ref flags() |
|
*/ |
|
CORRADE_IGNORE_DEPRECATED_PUSH /* GCC warns about Flag, ugh */ |
|
typedef CORRADE_DEPRECATED("use hasAttribute() etc. instead") Containers::EnumSet<Flag> Flags; |
|
CORRADE_IGNORE_DEPRECATED_POP |
|
#endif |
|
|
|
/** |
|
* @brief Construct |
|
* @param types Which material types are described by this |
|
* data. Can be an empty set. |
|
* @param attributeData Attribute data |
|
* @param importerState Importer-specific state |
|
* |
|
* The @p attributeData gets sorted by name internally, expecting no |
|
* duplicates. |
|
* |
|
* The @ref attributeDataFlags() / @ref layerDataFlags() are implicitly |
|
* set to a combination of @ref DataFlag::Owned and |
|
* @ref DataFlag::Mutable. For non-owned data use the |
|
* @ref MaterialData(MaterialTypes, DataFlags, Containers::ArrayView<const MaterialAttributeData>, const void*) |
|
* constructor instead. |
|
*/ |
|
explicit MaterialData(MaterialTypes types, Containers::Array<MaterialAttributeData>&& attributeData, const void* importerState = nullptr) noexcept: MaterialData{types, Utility::move(attributeData), nullptr, importerState} {} |
|
|
|
/** @overload */ |
|
/* Not noexcept because allocation happens inside */ |
|
explicit MaterialData(MaterialTypes types, std::initializer_list<MaterialAttributeData> attributeData, const void* importerState = nullptr): MaterialData{types, attributeData, {}, importerState} {} |
|
|
|
/** |
|
* @brief Construct a non-owned material data |
|
* @param types Which material types are described by |
|
* this data. Can be an empty set. |
|
* @param attributeDataFlags Attribute data flags |
|
* @param attributeData Attribute data |
|
* @param importerState Importer-specific state |
|
* |
|
* Compared to @ref MaterialData(MaterialTypes, Containers::Array<MaterialAttributeData>&&, const void*) |
|
* creates an instance that doesn't own the passed attribute data. The |
|
* @p attributeData is expected to be already sorted by name, without |
|
* duplicates. The @p attributeDataFlags can contain |
|
* @ref DataFlag::Mutable to indicate the external data can be |
|
* modified, and is expected to *not* have @ref DataFlag::Owned set. |
|
* The @ref layerDataFlags() are implicitly set to empty @ref DataFlags. |
|
*/ |
|
explicit MaterialData(MaterialTypes types, DataFlags attributeDataFlags, Containers::ArrayView<const MaterialAttributeData> attributeData, const void* importerState = nullptr) noexcept: MaterialData{types, attributeDataFlags, attributeData, {}, nullptr, importerState} {} |
|
|
|
/** |
|
* @brief Construct with layers |
|
* @param types Which material types are described by this |
|
* data. Can be an empty set. |
|
* @param attributeData Attribute data |
|
* @param layerData Layer offset data |
|
* @param importerState Importer-specific state |
|
* |
|
* The @p attributeData gets sorted by name internally, expecting no |
|
* duplicates inside each layer. The @p layerData is expected to be |
|
* either empty or a monotonically non-decreasing sequence of offsets |
|
* counting up to @p attributeData size, with *i*-th item specifying |
|
* end offset of *i*-th layer. |
|
* |
|
* The @ref attributeDataFlags() / @ref layerDataFlags() are implicitly |
|
* set to a combination of @ref DataFlag::Owned and |
|
* @ref DataFlag::Mutable. For non-owned data use the |
|
* @ref MaterialData(MaterialTypes, DataFlags, Containers::ArrayView<const MaterialAttributeData>, DataFlags, Containers::ArrayView<const UnsignedInt>, const void*) |
|
* constructor instead. |
|
*/ |
|
explicit MaterialData(MaterialTypes types, Containers::Array<MaterialAttributeData>&& attributeData, Containers::Array<UnsignedInt>&& layerData, const void* importerState = nullptr) noexcept; |
|
|
|
/** @overload */ |
|
/* Not noexcept because allocation happens inside */ |
|
explicit MaterialData(MaterialTypes types, std::initializer_list<MaterialAttributeData> attributeData, std::initializer_list<UnsignedInt> layerData, const void* importerState = nullptr); |
|
|
|
/** |
|
* @brief Construct a non-owned material data with layers |
|
* @param types Which material types are described by |
|
* this data. Can be an empty set. |
|
* @param attributeDataFlags Attribute data flags |
|
* @param attributeData Attribute data |
|
* @param layerDataFlags Layer offset data flags |
|
* @param layerData Layer offset data |
|
* @param importerState Importer-specific state |
|
* |
|
* The @p data is expected to be already sorted by name, without |
|
* duplicates inside each layer. The @p layerData is expected to be |
|
* either empty or a monotonically non-decreasing sequence of offsets |
|
* counting up to @p attributeData size, with *i*-th item specifying |
|
* end offset of *i*-th layer. |
|
* |
|
* The @p attributeDataFlags / @p layerDataFlags parameters can contain |
|
* @ref DataFlag::Mutable to indicate the external data can be |
|
* modified, and are expected to *not* have @ref DataFlag::Owned set. |
|
*/ |
|
/* The second (ignored) DataFlags is present in order to make it ready |
|
for a possible extension where only one of the data is non-owned. |
|
But so far I didn't see a need. */ |
|
explicit MaterialData(MaterialTypes types, DataFlags attributeDataFlags, Containers::ArrayView<const MaterialAttributeData> attributeData, DataFlags layerDataFlags, Containers::ArrayView<const UnsignedInt> layerData, const void* importerState = nullptr) noexcept; |
|
|
|
~MaterialData(); |
|
|
|
/** @brief Copying is not allowed */ |
|
MaterialData(const MaterialData&) = delete; |
|
|
|
/** @brief Move constructor */ |
|
MaterialData(MaterialData&&) noexcept; |
|
|
|
/** @brief Copying is not allowed */ |
|
MaterialData& operator=(const MaterialData&) = delete; |
|
|
|
/** @brief Move assignment */ |
|
MaterialData& operator=(MaterialData&&) noexcept; |
|
|
|
/** |
|
* @brief Attribute data flags |
|
*¨ |
|
* Since the attribute list is always assumed to be sorted and |
|
* partitioned into layers, only attribute values can be edited when |
|
* the @ref DataFlag::Mutable flag is present. |
|
* @see @ref releaseAttributeData(), @ref mutableAttribute() |
|
*/ |
|
DataFlags attributeDataFlags() const { return _attributeDataFlags; } |
|
|
|
/** |
|
* @brief Layer data flags |
|
* |
|
* Since the attribute list is always assumed to be sorted and |
|
* partitioned into layers, the @ref DataFlag::Mutable flag has no |
|
* effect here --- only attribute values can be edited when |
|
* @ref DataFlag::Mutable is present in @ref attributeDataFlags(). |
|
* @see @ref releaseLayerData() |
|
*/ |
|
DataFlags layerDataFlags() const { return _layerDataFlags; } |
|
|
|
/** |
|
* @brief Material types |
|
* |
|
* Each type indicates that the material data can be interpreted as |
|
* given type. For custom materials the set can also be empty. |
|
*/ |
|
MaterialTypes types() const { return _types; } |
|
|
|
/** |
|
* @brief Interpret as a material data of concrete type |
|
* |
|
* Returns a reference to @cpp *this @ce cast to given type. @p T is |
|
* expected to be a subclass of the same size such as |
|
* @ref PhongMaterialData or @ref PbrMetallicRoughnessMaterialData, as |
|
* well as layers like @ref PbrClearCoatMaterialData. |
|
*/ |
|
/* MSVC needs the & here, otherwise it complains that "cannot overload |
|
a member function with ref-qualifier with a member function without |
|
ref-qualifier". Clang or GCC doesn't. */ |
|
template<class T> const T& as() const & { |
|
static_assert(std::is_base_of<MaterialData, T>::value && sizeof(T) == sizeof(MaterialData), "expected a trivial subclass of MaterialData"); |
|
return static_cast<const T&>(*this); |
|
} |
|
|
|
/** |
|
* @brief Interpret a rvalue as a material data of concrete type |
|
* |
|
* Compared to the above, returns a value and not a reference. The |
|
* original instance then behaves the same as a moved-from instance. |
|
*/ |
|
template<class T> T as() && { |
|
return T{Utility::move(const_cast<T&>(as<T>()))}; |
|
} |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
/** |
|
* @brief Material type |
|
* @m_deprecated_since_latest Use @ref types() instead. |
|
*/ |
|
CORRADE_DEPRECATED("use types() instead") MaterialType type() const { |
|
return MaterialType(UnsignedInt(_types & MaterialType::Phong)); |
|
} |
|
#endif |
|
|
|
/** |
|
* @brief Raw layer offset data |
|
* |
|
* May return @cpp nullptr @ce if the material doesn't have any extra |
|
* layers. |
|
* @see @ref releaseLayerData() |
|
*/ |
|
Containers::ArrayView<const UnsignedInt> layerData() const { return _layerOffsets; } |
|
|
|
/** |
|
* @brief Raw attribute data |
|
* |
|
* Returns @cpp nullptr @ce if the material has no attributes. |
|
* @see @ref releaseAttributeData(), @ref attributeDataOffset(), |
|
* @ref attributeData(UnsignedInt, UnsignedInt) const, |
|
* @ref attributeData(UnsignedInt) const |
|
*/ |
|
Containers::ArrayView<const MaterialAttributeData> attributeData() const { return _data; } |
|
|
|
/** |
|
* @brief Layer count |
|
* |
|
* There's always at least the base material, so this function returns |
|
* at least @cpp 1 @ce. |
|
*/ |
|
UnsignedInt layerCount() const { |
|
return _layerOffsets.isEmpty() ? 1 : _layerOffsets.size(); |
|
} |
|
|
|
/** |
|
* @brief Offset of a layer inside attribute data |
|
* |
|
* Returns the offset where attributes for @p layer start in the array |
|
* returned by @ref attributeData() const. The @p layer is expected to |
|
* be less *or equal to* @ref layerCount(), i.e. it's always possible |
|
* to call this function with @cpp layer @ce and @cpp layer + 1 @ce to |
|
* get the attribute range for given layer, or with @ref layerCount() |
|
* to get the total attribute count in all layers. |
|
*/ |
|
UnsignedInt attributeDataOffset(UnsignedInt layer) const; |
|
|
|
/** |
|
* @brief Whether a material has given named layer |
|
* |
|
* Layers with no name assigned are skipped. The base material (layer |
|
* @cpp 0 @ce is skipped as well) to avoid confusing base material with |
|
* a layer. If you want to create a material consisting of just a |
|
* layer, use @cpp 0 @ce for the first layer offset in the constructor. |
|
* @see @ref hasAttribute(), @ref findLayerId() |
|
*/ |
|
bool hasLayer(Containers::StringView layer) const; |
|
bool hasLayer(MaterialLayer layer) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Find ID of a named layer |
|
* |
|
* The @p layer doesn't exist, returns |
|
* @relativeref{Corrade,Containers::NullOpt}. The lookup is done in an |
|
* @f$ \mathcal{O}(n) @f$ complexity with @f$ n @f$ being the layer |
|
* count. |
|
* @see @ref hasLayer() |
|
*/ |
|
Containers::Optional<UnsignedInt> findLayerId(Containers::StringView layer) const; |
|
Containers::Optional<UnsignedInt> findLayerId(MaterialLayer layer) const; /**< @overload */ |
|
|
|
/** |
|
* @brief ID of a named layer |
|
* |
|
* Like @ref findLayerId(), but the @p layer is expected to exist. |
|
* @see @ref hasLayer() |
|
*/ |
|
UnsignedInt layerId(Containers::StringView layer) const; |
|
UnsignedInt layerId(MaterialLayer layer) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Layer name |
|
* |
|
* Retrieves a @ref MaterialAttribute::LayerName attribute from given |
|
* layer, if present. Returns a @cpp nullptr @ce view if the layer |
|
* has no name, and an empty non-null view if the layer name is empty. |
|
* The @p layer is expected to be smaller than @ref layerCount() const. |
|
* |
|
* The name, if present, is ignored for the base material (layer |
|
* @cpp 0 @ce) to avoid confsing base material with a layer. If you |
|
* want to create a material consisting of just a layer, use @cpp 0 @ce |
|
* for the first layer offset in the constructor. |
|
* @see @ref materialLayerName() |
|
*/ |
|
Containers::StringView layerName(UnsignedInt layer) const; |
|
|
|
/** |
|
* @brief Factor of given layer |
|
* |
|
* Convenience access to the @ref MaterialAttribute::LayerFactor |
|
* attribute. If not present, the default is @cpp 1.0f @ce. The |
|
* @p layer is expected to be smaller than @ref layerCount() const. |
|
* |
|
* If the layer has @ref MaterialAttribute::LayerFactorTexture, the |
|
* factor and texture is meant to be multiplied together. |
|
*/ |
|
Float layerFactor(UnsignedInt layer) const; |
|
|
|
/** |
|
* @brief Factor of a named layer |
|
* |
|
* Convenience access to the @ref MaterialAttribute::LayerFactor |
|
* attribute. If not present, the default is @cpp 1.0f @ce. The |
|
* @p layer is expected to exist. |
|
* |
|
* If the layer has @ref MaterialAttribute::LayerFactorTexture, the |
|
* factor and texture is meant to be multiplied together. |
|
* @see @ref hasLayer() |
|
*/ |
|
Float layerFactor(Containers::StringView layer) const; |
|
Float layerFactor(MaterialLayer layer) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Factor texture ID for given layer |
|
* |
|
* Available only if the @ref MaterialAttribute::LayerFactorTexture |
|
* attribute is present. Meant to be multiplied with @ref layerFactor(). |
|
* The @p layer is expected to be smaller than @ref layerCount(). |
|
* @see @ref hasAttribute() |
|
*/ |
|
UnsignedInt layerFactorTexture(UnsignedInt layer) const; |
|
|
|
/** |
|
* @brief Factor texture ID for a named layer |
|
* |
|
* Available only if the @ref MaterialAttribute::LayerFactorTexture |
|
* attribute is present. Meant to be multiplied with @ref layerFactor(). |
|
* The @p layer is expected to exist. |
|
* @see @ref hasLayer(), @ref hasAttribute() |
|
*/ |
|
UnsignedInt layerFactorTexture(Containers::StringView layer) const; |
|
UnsignedInt layerFactorTexture(MaterialLayer layer) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Factor texture swizzle for given layer |
|
* |
|
* Convenience access to the @ref MaterialAttribute::LayerFactorTextureSwizzle |
|
* attribute. If not present, the default is @ref MaterialTextureSwizzle::R. |
|
* Available only if the @ref MaterialAttribute::LayerFactorTexture |
|
* attribute is present. The @p layer is expected to be smaller than |
|
* @ref layerCount(). |
|
* @see @ref hasAttribute() |
|
*/ |
|
MaterialTextureSwizzle layerFactorTextureSwizzle(UnsignedInt layer) const; |
|
|
|
/** |
|
* @brief Factor texture swizzle for a named layer |
|
* |
|
* Convenience access to the @ref MaterialAttribute::LayerFactorTextureSwizzle |
|
* attribute. If not present, the default is @ref MaterialTextureSwizzle::R. |
|
* Available only if the @ref MaterialAttribute::LayerFactorTexture |
|
* attribute is present. The @p layer is expected to exist. |
|
* @see @ref hasLayer(), @ref hasAttribute() |
|
*/ |
|
MaterialTextureSwizzle layerFactorTextureSwizzle(Containers::StringView layer) const; |
|
MaterialTextureSwizzle layerFactorTextureSwizzle(MaterialLayer layer) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Factor texture coordinate transformation matrix for given layer |
|
* |
|
* Convenience access to the @ref MaterialAttribute::LayerFactorTextureMatrix |
|
* / @ref MaterialAttribute::TextureMatrix attributes in given layer or |
|
* a @ref MaterialAttribute::TextureMatrix attribute in the base |
|
* material. If neither is present, the default is an identity matrix. |
|
* Available only if the @ref MaterialAttribute::LayerFactorTexture |
|
* attribute is present. The @p layer is expected to be smaller than |
|
* @ref layerCount(). |
|
* @see @ref hasAttribute() |
|
*/ |
|
Matrix3 layerFactorTextureMatrix(UnsignedInt layer) const; |
|
|
|
/** |
|
* @brief Factor texture coordinate transformation matrix for a named layer |
|
* |
|
* Convenience access to the @ref MaterialAttribute::LayerFactorTextureMatrix |
|
* / @ref MaterialAttribute::TextureMatrix attributes in given layer or |
|
* a @ref MaterialAttribute::TextureMatrix attribute in the base |
|
* material. If neither is present, the default is an identity matrix. |
|
* Available only if the @ref MaterialAttribute::LayerFactorTexture |
|
* attribute is present. The @p layer is expected to exist. |
|
* @see @ref hasLayer(), @ref hasAttribute() |
|
*/ |
|
Matrix3 layerFactorTextureMatrix(Containers::StringView layer) const; |
|
Matrix3 layerFactorTextureMatrix(MaterialLayer layer) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Factor texture coordinate set for given layer |
|
* |
|
* Convenience access to the @ref MaterialAttribute::LayerFactorTextureCoordinates |
|
* / @ref MaterialAttribute::TextureCoordinates attributes in given |
|
* layer or a @ref MaterialAttribute::TextureCoordinates attribute in |
|
* the base material. If neither is present, the default is @cpp 0 @ce. |
|
* Available only if the @ref MaterialAttribute::LayerFactorTexture |
|
* attribute is present. The @p layer is expected to be smaller than |
|
* @ref layerCount(). |
|
* @see @ref hasAttribute() |
|
*/ |
|
UnsignedInt layerFactorTextureCoordinates(UnsignedInt layer) const; |
|
|
|
/** |
|
* @brief Factor texture coordinate set for a named layer |
|
* |
|
* Convenience access to the @ref MaterialAttribute::LayerFactorTextureCoordinates |
|
* / @ref MaterialAttribute::TextureCoordinates attributes in given |
|
* layer or a @ref MaterialAttribute::TextureCoordinates attribute in |
|
* the base material. If neither is present, the default is @cpp 0 @ce. |
|
* Available only if the @ref MaterialAttribute::LayerFactorTexture |
|
* attribute is present. The @p layer is expected to exist. |
|
* @see @ref hasLayer(), @ref hasAttribute() |
|
*/ |
|
UnsignedInt layerFactorTextureCoordinates(Containers::StringView layer) const; |
|
UnsignedInt layerFactorTextureCoordinates(MaterialLayer layer) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Factor array texture layer for given layer |
|
* |
|
* Convenience access to the @ref MaterialAttribute::LayerFactorTextureLayer |
|
* / @ref MaterialAttribute::TextureLayer attributes in given layer or |
|
* a @ref MaterialAttribute::TextureLayer attribute in the base |
|
* material. If neither is present, the default is @cpp 0 @ce. |
|
* Available only if the @ref MaterialAttribute::LayerFactorTexture |
|
* attribute is present. The @p layer is expected to be smaller than |
|
* @ref layerCount(). |
|
* @see @ref hasAttribute() |
|
*/ |
|
UnsignedInt layerFactorTextureLayer(UnsignedInt layer) const; |
|
|
|
/** |
|
* @brief Factor array texture layer for a named layer |
|
* |
|
* Convenience access to the @ref MaterialAttribute::LayerFactorTextureLayer |
|
* / @ref MaterialAttribute::TextureLayer attributes in given layer or |
|
* a @ref MaterialAttribute::TextureLayer attribute in the base |
|
* material. If neither is present, the default is @cpp 0 @ce. |
|
* Available only if the @ref MaterialAttribute::LayerFactorTexture |
|
* attribute is present. The @p layer is expected to exist. |
|
* @see @ref hasLayer(), @ref hasAttribute() |
|
*/ |
|
UnsignedInt layerFactorTextureLayer(Containers::StringView layer) const; |
|
UnsignedInt layerFactorTextureLayer(MaterialLayer layer) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Attribute count in given layer |
|
* |
|
* The @p layer is expected to be smaller than @ref layerCount() const. |
|
*/ |
|
UnsignedInt attributeCount(UnsignedInt layer) const; |
|
|
|
/** |
|
* @brief Attribute count in a named layer |
|
* |
|
* The @p layer is expected to exist. |
|
* @see @ref hasLayer() |
|
*/ |
|
UnsignedInt attributeCount(Containers::StringView layer) const; |
|
UnsignedInt attributeCount(MaterialLayer layer) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Attribute count in the base material |
|
* |
|
* Equivalent to calling @ref attributeCount(UnsignedInt) const with |
|
* @p layer set to @cpp 0 @ce. |
|
*/ |
|
UnsignedInt attributeCount() const { return attributeCount(0); } |
|
|
|
/** |
|
* @brief Whether a material layer has given attribute |
|
* |
|
* The @p layer is expected to be smaller than @ref layerCount() const. |
|
* @see @ref findAttribute(), @ref attributeOr(), @ref hasLayer(), |
|
* @ref findAttributeId() |
|
*/ |
|
bool hasAttribute(UnsignedInt layer, Containers::StringView name) const; |
|
bool hasAttribute(UnsignedInt layer, MaterialAttribute name) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Whether a named material layer has given attribute |
|
* |
|
* The @p layer is expected to exist. |
|
* @see @ref findAttribute(), @ref attributeOr(), @ref hasLayer(), |
|
* @ref findAttributeId() |
|
*/ |
|
bool hasAttribute(Containers::StringView layer, Containers::StringView name) const; |
|
bool hasAttribute(Containers::StringView layer, MaterialAttribute name) const; /**< @overload */ |
|
bool hasAttribute(MaterialLayer layer, Containers::StringView name) const; /**< @overload */ |
|
bool hasAttribute(MaterialLayer layer, MaterialAttribute name) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Whether the base material has given attribute |
|
* |
|
* Equivalent to calling @ref hasAttribute(UnsignedInt, Containers::StringView) const |
|
* with @p layer set to @cpp 0 @ce. |
|
* @see @ref findAttribute(), @ref attributeOr(), |
|
* @ref findAttributeId() |
|
*/ |
|
bool hasAttribute(Containers::StringView name) const { |
|
return hasAttribute(0, name); |
|
} |
|
bool hasAttribute(MaterialAttribute name) const { |
|
return hasAttribute(0, name); |
|
} /**< @overload */ |
|
|
|
/** |
|
* @brief Find ID of a named attribute in given material layer |
|
* |
|
* If @p name doesn't exist, returns |
|
* @relativeref{Corrade,Containers::NullOpt}. The @p layer is expected |
|
* to be smaller than @ref layerCount() const. The lookup is done in an |
|
* @f$ \mathcal{O}(\log n) @f$ complexity with @f$ n @f$ being |
|
* attribute count in given @p layer. |
|
* @see @ref hasAttribute(), @ref attributeId() |
|
*/ |
|
Containers::Optional<UnsignedInt> findAttributeId(UnsignedInt layer, Containers::StringView name) const; |
|
Containers::Optional<UnsignedInt> findAttributeId(UnsignedInt layer, MaterialAttribute name) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Find ID of a named attribute in a named material layer |
|
* |
|
* If @p name doesn't exist, returns |
|
* @relativeref{Corrade,Containers::NullOpt}. The @p layer is expected |
|
* to exist. The lookup is done in an @f$ \mathcal{O}(m + \log n) @f$ |
|
* complexity with @f$ m @f$ being layer count and @f$ n @f$ being |
|
* attribute count in given @p layer. |
|
* @see @ref hasLayer(), @ref hasAttribute(), @ref attributeId(), |
|
* @ref findLayerId() |
|
*/ |
|
Containers::Optional<UnsignedInt> findAttributeId(Containers::StringView layer, Containers::StringView name) const; |
|
Containers::Optional<UnsignedInt> findAttributeId(Containers::StringView layer, MaterialAttribute name) const; /**< @overload */ |
|
Containers::Optional<UnsignedInt> findAttributeId(MaterialLayer layer, Containers::StringView name) const; /**< @overload */ |
|
Containers::Optional<UnsignedInt> findAttributeId(MaterialLayer layer, MaterialAttribute name) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Find ID of a named attribute in the base material |
|
* |
|
* Equivalent to calling @ref findAttributeId(UnsignedInt, Containers::StringView) const |
|
* with @p layer set to @cpp 0 @ce. |
|
*/ |
|
Containers::Optional<UnsignedInt> findAttributeId(Containers::StringView name) const; |
|
Containers::Optional<UnsignedInt> findAttributeId(MaterialAttribute name) const; /**< @overload */ |
|
|
|
/** |
|
* @brief ID of a named attribute in given material layer |
|
* |
|
* Like @ref findAttributeId(UnsignedInt, Containers::StringView) const, |
|
* but the @p name is expected to exist. |
|
* @see @ref hasAttribute(), |
|
* @ref attributeName(UnsignedInt, UnsignedInt) const |
|
*/ |
|
UnsignedInt attributeId(UnsignedInt layer, Containers::StringView name) const; |
|
UnsignedInt attributeId(UnsignedInt layer, MaterialAttribute name) const; /**< @overload */ |
|
|
|
/** |
|
* @brief ID of a named attribute in a named material layer |
|
* |
|
* Like @ref findAttributeId(Containers::StringView, Containers::StringView) const, |
|
* but the @p name is expected to exist. |
|
* @see @ref hasLayer(), @ref hasAttribute() |
|
*/ |
|
UnsignedInt attributeId(Containers::StringView layer, Containers::StringView name) const; |
|
UnsignedInt attributeId(Containers::StringView layer, MaterialAttribute name) const; /**< @overload */ |
|
UnsignedInt attributeId(MaterialLayer layer, Containers::StringView name) const; /**< @overload */ |
|
UnsignedInt attributeId(MaterialLayer layer, MaterialAttribute name) const; /**< @overload */ |
|
|
|
/** |
|
* @brief ID of a named attribute in the base material |
|
* |
|
* Equivalent to calling @ref attributeId(UnsignedInt, Containers::StringView) const |
|
* with @p layer set to @cpp 0 @ce. |
|
*/ |
|
UnsignedInt attributeId(Containers::StringView name) const { |
|
return attributeId(0, name); |
|
} |
|
UnsignedInt attributeId(MaterialAttribute name) const { |
|
return attributeId(0, name); |
|
} /**< @overload */ |
|
|
|
/** |
|
* @brief Raw attribute data |
|
* |
|
* The @p layer is expected to be smaller than @ref layerCount() const, |
|
* @p id is expected to be smaller than @ref attributeCount(UnsignedInt) const. |
|
* @see @ref attributeDataOffset() |
|
*/ |
|
const MaterialAttributeData& attributeData(UnsignedInt layer, UnsignedInt id) const; |
|
|
|
/** |
|
* @brief Raw attribute data in the base material |
|
* |
|
* The @p @p id is expected to be smaller than @ref attributeCount() const. |
|
* @see @ref attributeDataOffset() |
|
*/ |
|
const MaterialAttributeData& attributeData(UnsignedInt id) const { |
|
return attributeData(0, id); |
|
} |
|
|
|
/** |
|
* @brief Name of an attribute in given material layer |
|
* |
|
* The @p layer is expected to be smaller than @ref layerCount() const |
|
* and the @p id is expected to be smaller than @ref attributeCount(UnsignedInt) const |
|
* in that layer. The returned view always has |
|
* @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} set. |
|
* @see @ref attributeType(), @ref materialAttributeName() |
|
*/ |
|
Containers::StringView attributeName(UnsignedInt layer, UnsignedInt id) const; |
|
|
|
/** |
|
* @brief Name of an attribute in a named material layer |
|
* |
|
* The @p layer is expected to exist and the @p id is expected to be smaller than @ref attributeCount(UnsignedInt) const |
|
* in that layer. |
|
* @see @ref hasLayer(), @ref materialAttributeName() |
|
*/ |
|
Containers::StringView attributeName(Containers::StringView layer, UnsignedInt id) const; |
|
Containers::StringView attributeName(MaterialLayer layer, UnsignedInt id) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Name of an attribute in the base material |
|
* |
|
* Equivalent to calling @ref attributeName(UnsignedInt, UnsignedInt) const |
|
* with @p layer set to @cpp 0 @ce. |
|
* @see @ref materialAttributeName() |
|
*/ |
|
Containers::StringView attributeName(UnsignedInt id) const { |
|
return attributeName(0, id); |
|
} |
|
|
|
/** |
|
* @brief Type of an attribute in given material layer |
|
* |
|
* The @p layer is expected to be smaller than @ref layerCount() const |
|
* and @p id is expected to be smaller than @ref attributeCount(UnsignedInt) const |
|
* in that layer. |
|
* @see @ref attributeName() |
|
*/ |
|
MaterialAttributeType attributeType(UnsignedInt layer, UnsignedInt id) const; |
|
|
|
/** |
|
* @brief Type of a named attribute in given material layer |
|
* |
|
* The @p layer is expected to be smaller than @ref layerCount() const |
|
* and @p name is expected to exist in that layer. |
|
* @see @ref hasAttribute() |
|
*/ |
|
MaterialAttributeType attributeType(UnsignedInt layer, Containers::StringView name) const; |
|
/** @overload */ |
|
MaterialAttributeType attributeType(UnsignedInt layer, MaterialAttribute name) const; |
|
|
|
/** |
|
* @brief Type of an attribute in a named material layer |
|
* |
|
* The @p layer is expected to exist and the @p id is expected to be smaller than @ref attributeCount(UnsignedInt) const |
|
* in that layer. |
|
* @see @ref hasLayer() |
|
*/ |
|
MaterialAttributeType attributeType(Containers::StringView layer, UnsignedInt id) const; |
|
MaterialAttributeType attributeType(MaterialLayer layer, UnsignedInt id) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Type of a named attribute in a named material layer |
|
* |
|
* The @p layer is expected to exist and @p name is expected to exist |
|
* in that layer. |
|
* @see @ref hasLayer(), @ref hasAttribute() |
|
*/ |
|
MaterialAttributeType attributeType(Containers::StringView layer, Containers::StringView name) const; |
|
MaterialAttributeType attributeType(Containers::StringView layer, MaterialAttribute name) const; /**< @overload */ |
|
MaterialAttributeType attributeType(MaterialLayer layer, Containers::StringView name) const; /**< @overload */ |
|
MaterialAttributeType attributeType(MaterialLayer layer, MaterialAttribute name) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Type of an attribute in the base material |
|
* |
|
* Equivalent to calling @ref attributeType(UnsignedInt, UnsignedInt) const |
|
* with @p layer set to @cpp 0 @ce. |
|
*/ |
|
MaterialAttributeType attributeType(UnsignedInt id) const { |
|
return attributeType(0, id); |
|
} |
|
|
|
/** |
|
* @brief Type of a named attribute in the base material |
|
* |
|
* Equivalent to calling @ref attributeType(UnsignedInt, Containers::StringView) const |
|
* with @p layer set to @cpp 0 @ce. |
|
*/ |
|
MaterialAttributeType attributeType(Containers::StringView name) const { |
|
return attributeType(0, name); |
|
} |
|
MaterialAttributeType attributeType(MaterialAttribute name) const { |
|
return attributeType(0, name); |
|
} /**< @overload */ |
|
|
|
/** |
|
* @brief Type-erased value of an attribute in given material layer |
|
* |
|
* The @p layer is expected to be smaller than @ref layerCount() const |
|
* and @p id is expected to be smaller than @ref attributeCount(UnsignedInt) const |
|
* in that layer. Cast the pointer to a concrete type based on |
|
* @ref type(). |
|
* |
|
* - In case of a @ref MaterialAttributeType::Pointer or a |
|
* @ref MaterialAttributeType::MutablePointer, returns a |
|
* *pointer to a pointer*, not the pointer value itself. |
|
* - In case of a @ref MaterialAttributeType::String returns a |
|
* null-terminated @cpp const char* @ce (not a pointer to |
|
* @relativeref{Corrade,Containers::StringView}). This doesn't |
|
* preserve the actual string size in case the string data contain |
|
* zero bytes, thus prefer to use typed access in that case. |
|
* - In case of a @ref MaterialAttributeType::Buffer returns a |
|
* pointer to the data with no size information, Prefer to use |
|
* typed access in that case. |
|
*/ |
|
const void* attribute(UnsignedInt layer, UnsignedInt id) const; |
|
|
|
/** |
|
* @brief Type-erased mutable value of an attribute in given material layer |
|
* |
|
* Like @ref attribute(UnsignedInt, UnsignedInt) const but returns a |
|
* mutable pointer. Expects that the material is mutable. |
|
* @see @ref attributeDataFlags() |
|
*/ |
|
void* mutableAttribute(UnsignedInt layer, UnsignedInt id); |
|
|
|
/** |
|
* @brief Type-erased value of a named attribute in given material layer |
|
* |
|
* The @p layer is expected to be smaller than @ref layerCount() const |
|
* and @p name is expected to exist in that layer. Cast the pointer to |
|
* a concrete type based on @ref attributeType(). |
|
* |
|
* - In case of a @ref MaterialAttributeType::Pointer or a |
|
* @ref MaterialAttributeType::MutablePointer, returns a |
|
* *pointer to a pointer*, not the pointer value itself. |
|
* - In case of a @ref MaterialAttributeType::String returns a |
|
* null-terminated @cpp const char* @ce (not a pointer to |
|
* @relativeref{Corrade,Containers::StringView}). This doesn't |
|
* preserve the actual string size in case the string data contain |
|
* zero bytes, thus prefer to use typed access in that case. |
|
* - In case of a @ref MaterialAttributeType::Buffer returns a |
|
* pointer to the data with no size information, Prefer to use |
|
* typed access in that case. |
|
* |
|
* @see @ref hasAttribute(), @ref findAttribute(), @ref attributeOr() |
|
*/ |
|
const void* attribute(UnsignedInt layer, Containers::StringView name) const; |
|
const void* attribute(UnsignedInt layer, MaterialAttribute name) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Type-erased value of a named attribute in given material layer |
|
* |
|
* Like @ref attribute(UnsignedInt, Containers::StringView) const, but |
|
* returns a mutable pointer. Expects that the material is mutable. |
|
* @see @ref attributeDataFlags() |
|
*/ |
|
void* mutableAttribute(UnsignedInt layer, Containers::StringView name); |
|
void* mutableAttribute(UnsignedInt layer, MaterialAttribute name); /**< @overload */ |
|
|
|
/** |
|
* @brief Type-erased value of an attribute in a named material layer |
|
* |
|
* The @p layer is expected to exist and the @p id is expected to be smaller than @ref attributeCount(UnsignedInt) const |
|
* in that layer. Cast the pointer to a concrete type based on |
|
* @ref attributeType(). |
|
* |
|
* - In case of a @ref MaterialAttributeType::Pointer or a |
|
* @ref MaterialAttributeType::MutablePointer, returns a |
|
* *pointer to a pointer*, not the pointer value itself. |
|
* - In case of a @ref MaterialAttributeType::String returns a |
|
* null-terminated @cpp const char* @ce (not a pointer to |
|
* @relativeref{Corrade,Containers::StringView}). This doesn't |
|
* preserve the actual string size in case the string data contain |
|
* zero bytes, thus prefer to use typed access in that case. |
|
* - In case of a @ref MaterialAttributeType::Buffer returns a |
|
* pointer to the data with no size information, Prefer to use |
|
* typed access in that case. |
|
* |
|
* @see @ref hasLayer() |
|
*/ |
|
const void* attribute(Containers::StringView layer, UnsignedInt id) const; |
|
const void* attribute(MaterialLayer layer, UnsignedInt id) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Type-erased mutable value of an attribute in a named material layer |
|
* |
|
* Like @ref attribute(Containers::StringView, UnsignedInt) const but |
|
* returns a mutable pointer. Expects that the material is mutable. |
|
* @see @ref attributeDataFlags() |
|
*/ |
|
void* mutableAttribute(Containers::StringView layer, UnsignedInt id); |
|
void* mutableAttribute(MaterialLayer layer, UnsignedInt id); /**< @overload */ |
|
|
|
/** |
|
* @brief Type-erased value of a named attribute in a named material layer |
|
* |
|
* The @p layer is expected to exist and @p name is expected to exist |
|
* in that layer. Cast the pointer to a concrete type based on |
|
* @ref attributeType(). |
|
* |
|
* - In case of a @ref MaterialAttributeType::Pointer or a |
|
* @ref MaterialAttributeType::MutablePointer, returns a |
|
* *pointer to a pointer*, not the pointer value itself. |
|
* - In case of a @ref MaterialAttributeType::String returns a |
|
* null-terminated @cpp const char* @ce (not a pointer to |
|
* @relativeref{Corrade,Containers::StringView}). This doesn't |
|
* preserve the actual string size in case the string data contain |
|
* zero bytes, thus prefer to use typed access in that case. |
|
* - In case of a @ref MaterialAttributeType::Buffer returns a |
|
* pointer to the data with no size information, Prefer to use |
|
* typed access in that case. |
|
* |
|
* @see @ref hasLayer(), @ref hasAttribute() |
|
*/ |
|
const void* attribute(Containers::StringView layer, Containers::StringView name) const; |
|
const void* attribute(Containers::StringView layer, MaterialAttribute name) const; /**< @overload */ |
|
const void* attribute(MaterialLayer layer, Containers::StringView name) const; /**< @overload */ |
|
const void* attribute(MaterialLayer layer, MaterialAttribute name) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Type-erased mutable value of a named attribute in a named material layer |
|
* |
|
* Like @ref attribute(Containers::StringView, Containers::StringView) const |
|
* but returns a mutable pointer. Expects that the material is mutable. |
|
* @see @ref attributeDataFlags() |
|
*/ |
|
void* mutableAttribute(Containers::StringView layer, Containers::StringView name); |
|
void* mutableAttribute(Containers::StringView layer, MaterialAttribute name); /**< @overload */ |
|
void* mutableAttribute(MaterialLayer layer, Containers::StringView name); /**< @overload */ |
|
void* mutableAttribute(MaterialLayer layer, MaterialAttribute name); /**< @overload */ |
|
|
|
/** |
|
* @brief Type-erased value of an attribute in the base material |
|
* |
|
* Equivalent to calling @ref attribute(UnsignedInt, UnsignedInt) const |
|
* with @p layer set to @cpp 0 @ce. |
|
*/ |
|
const void* attribute(UnsignedInt id) const { |
|
return attribute(0, id); |
|
} |
|
|
|
/** |
|
* @brief Type-erased mutable value of an attribute in the base material |
|
* |
|
* Like @ref attribute(UnsignedInt) const but returns a mutable |
|
* pointer. Expects that the material is mutable. |
|
* @see @ref attributeDataFlags() |
|
*/ |
|
void* mutableAttribute(UnsignedInt id) { |
|
return mutableAttribute(0, id); |
|
} |
|
|
|
/** |
|
* @brief Type-erased value of a named attribute in the base material |
|
* |
|
* Equivalent to calling @ref attribute(UnsignedInt, Containers::StringView) const |
|
* with @p layer set to @cpp 0 @ce. |
|
*/ |
|
const void* attribute(Containers::StringView name) const { |
|
return attribute(0, name); |
|
} |
|
const void* attribute(MaterialAttribute name) const { |
|
return attribute(0, name); |
|
} /**< @overload */ |
|
|
|
/** |
|
* @brief Type-erased mutable value of a named attribute in the base material |
|
* |
|
* Like @ref attribute(Containers::StringView) const but returns a |
|
* mutable pointer. Expects that the material is mutable. |
|
* @see @ref attributeDataFlags() |
|
*/ |
|
void* mutableAttribute(Containers::StringView name) { |
|
return mutableAttribute(0, name); |
|
} |
|
void* mutableAttribute(MaterialAttribute name) { |
|
return mutableAttribute(0, name); |
|
} /**< @overload */ |
|
|
|
/** |
|
* @brief Value of an attribute in given material layer |
|
* |
|
* The @p layer is expected to be smaller than @ref layerCount() const |
|
* and @p id is expected to be smaller than |
|
* @ref attributeCount(UnsignedInt) const in that layer. Expects that |
|
* @p T corresponds to @ref attributeType(UnsignedInt, UnsignedInt) const |
|
* for given @p layer and @p id. In case of a string, the returned view |
|
* always has @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} |
|
* set. |
|
*/ |
|
template<class T> T attribute(UnsignedInt layer, UnsignedInt id) const; |
|
|
|
/** |
|
* @brief Mutable value of an attribute in given material layer |
|
* |
|
* Like @ref attribute(UnsignedInt, UnsignedInt) const but returns a |
|
* mutable reference. Expects that the material is mutable. In case of |
|
* a string / buffer, you're expected to use |
|
* @relativeref{Corrade,Containers::MutableStringView} / |
|
* @relativeref{Corrade,Containers::ArrayView<void>} instead of |
|
* @relativeref{Corrade,Containers::StringView} / |
|
* @relativeref{Corrade,Containers::ArrayView<const void>} for @p T and |
|
* you get a @relativeref{Corrade,Containers::MutableStringView} / |
|
* @relativeref{Corrade,Containers::ArrayView<void>} back by-value, not |
|
* by-reference. Changing the string / buffer size is not possible. |
|
* @see @ref attributeDataFlags() |
|
*/ |
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type mutableAttribute(UnsignedInt layer, UnsignedInt id); |
|
|
|
/** |
|
* @brief Value of a named attribute in given material layer |
|
* |
|
* The @p layer is expected to be smaller than @ref layerCount() const |
|
* and @p name is expected to exist in that layer. Expects that @p T |
|
* corresponds to @ref attributeType(UnsignedInt, Containers::StringView) const |
|
* for given @p layer and @p name. In case of a string, the returned |
|
* view always has @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} |
|
* set. |
|
* @see @ref hasLayer(), @ref hasAttribute() |
|
*/ |
|
template<class T> T attribute(UnsignedInt layer, Containers::StringView name) const; |
|
template<class T> T attribute(UnsignedInt layer, MaterialAttribute name) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Mutable value of a named attribute in given material layer |
|
* |
|
* Like @ref attribute(UnsignedInt, Containers::StringView) const but |
|
* returns a mutable reference. Expects that the material is mutable. |
|
* In case of a string / buffer, you're expected to use |
|
* @relativeref{Corrade,Containers::MutableStringView} / |
|
* @relativeref{Corrade,Containers::ArrayView<void>} instead of |
|
* @relativeref{Corrade,Containers::StringView} / |
|
* @relativeref{Corrade,Containers::ArrayView<const void>} for @p T and |
|
* you get a @relativeref{Corrade,Containers::MutableStringView} / |
|
* @relativeref{Corrade,Containers::ArrayView<void>} back by-value, not |
|
* by-reference. Changing the string / buffer size is not possible. |
|
* @see @ref attributeDataFlags() |
|
*/ |
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type mutableAttribute(UnsignedInt layer, Containers::StringView name); |
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type mutableAttribute(UnsignedInt layer, MaterialAttribute name); /**< @overload */ |
|
|
|
/** |
|
* @brief Value of an attribute in a named material layer |
|
* |
|
* The @p layer is expected to exist and @p id is expected to be |
|
* smaller than @ref attributeCount(UnsignedInt) const in that layer. |
|
* Expects that @p T corresponds to |
|
* @ref attributeType(Containers::StringView, UnsignedInt) const |
|
* for given @p layer and @p id. In case of a string, the returned view |
|
* always has @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} |
|
* set. |
|
* @see @ref hasLayer() |
|
*/ |
|
template<class T> T attribute(Containers::StringView layer, UnsignedInt id) const; |
|
template<class T> T attribute(MaterialLayer layer, UnsignedInt id) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Mutable value of an attribute in a named material layer |
|
* |
|
* Like @ref attribute(Containers::StringView, UnsignedInt) const but |
|
* returns a mutable reference. Expects that the material is mutable. |
|
* In case of a string / buffer, you're expected to use |
|
* @relativeref{Corrade,Containers::MutableStringView} / |
|
* @relativeref{Corrade,Containers::ArrayView<void>} instead of |
|
* @relativeref{Corrade,Containers::StringView} / |
|
* @relativeref{Corrade,Containers::ArrayView<const void>} for @p T and |
|
* you get a @relativeref{Corrade,Containers::MutableStringView} / |
|
* @relativeref{Corrade,Containers::ArrayView<void>} back by-value, not |
|
* by-reference. Changing the string / buffer size is not possible. |
|
* @see @ref attributeDataFlags() |
|
*/ |
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type mutableAttribute(Containers::StringView layer, UnsignedInt id); |
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type mutableAttribute(MaterialLayer layer, UnsignedInt id); /**< @overload */ |
|
|
|
/** |
|
* @brief Value of a named attribute in a named material layer |
|
* |
|
* The @p layer is expected to exist and @p name is expected to exist |
|
* in that layer. Expects that @p T corresponds to |
|
* @ref attributeType(Containers::StringView, Containers::StringView) const |
|
* for given @p layer and @p name. In case of a string, the returned |
|
* view always has @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} |
|
* set. |
|
* @see @ref hasLayer(), @ref hasAttribute() |
|
*/ |
|
template<class T> T attribute(Containers::StringView layer, Containers::StringView name) const; |
|
template<class T> T attribute(Containers::StringView layer, MaterialAttribute name) const; /**< @overload */ |
|
template<class T> T attribute(MaterialLayer layer, Containers::StringView name) const; /**< @overload */ |
|
template<class T> T attribute(MaterialLayer layer, MaterialAttribute name) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Mutable value of a named attribute in a named material layer |
|
* |
|
* Like @ref attribute(Containers::StringView, Containers::StringView) const |
|
* but returns a mutable reference. Expects that the material is |
|
* mutable. In case of a string / buffer, you're expected to use |
|
* @relativeref{Corrade,Containers::MutableStringView} / |
|
* @relativeref{Corrade,Containers::ArrayView<void>} instead of |
|
* @relativeref{Corrade,Containers::StringView} / |
|
* @relativeref{Corrade,Containers::ArrayView<const void>} for @p T and |
|
* you get a @relativeref{Corrade,Containers::MutableStringView} / |
|
* @relativeref{Corrade,Containers::ArrayView<void>} back by-value, not |
|
* by-reference. Changing the string / buffer size is not possible. |
|
* @see @ref attributeDataFlags() |
|
*/ |
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type mutableAttribute(Containers::StringView layer, Containers::StringView name); |
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type mutableAttribute(Containers::StringView layer, MaterialAttribute name); /**< @overload */ |
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type mutableAttribute(MaterialLayer layer, Containers::StringView name); /**< @overload */ |
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type mutableAttribute(MaterialLayer layer, MaterialAttribute name); /**< @overload */ |
|
|
|
/** |
|
* @brief Value of an attribute in the base material |
|
* |
|
* Equivalent to calling @ref attribute(UnsignedInt, UnsignedInt) const |
|
* with @p layer set to @cpp 0 @ce. |
|
*/ |
|
template<class T> T attribute(UnsignedInt id) const { |
|
return attribute<T>(0, id); |
|
} |
|
|
|
/** |
|
* @brief Mutable value of an attribute in the base material |
|
* |
|
* Equivalent to calling @ref mutableAttribute(UnsignedInt, UnsignedInt) |
|
* with @p layer set to @cpp 0 @ce. |
|
*/ |
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type mutableAttribute(UnsignedInt id) { |
|
return mutableAttribute<T>(0, id); |
|
} |
|
|
|
/** |
|
* @brief Value of a named attribute in the base material |
|
* |
|
* Equivalent to calling @ref attribute(UnsignedInt, Containers::StringView) const |
|
* with @p layer set to @cpp 0 @ce. |
|
*/ |
|
template<class T> T attribute(Containers::StringView name) const { |
|
return attribute<T>(0, name); |
|
} |
|
template<class T> T attribute(MaterialAttribute name) const { |
|
return attribute<T>(0, name); |
|
} /**< @overload */ |
|
|
|
/** |
|
* @brief Mutable value of a named attribute in the base material |
|
* |
|
* Equivalent to calling @ref mutableAttribute(UnsignedInt, Containers::StringView) |
|
* with @p layer set to @cpp 0 @ce. |
|
*/ |
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type mutableAttribute(Containers::StringView name) { |
|
return mutableAttribute<T>(0, name); |
|
} |
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type mutableAttribute(MaterialAttribute name) { |
|
return mutableAttribute<T>(0, name); |
|
} /**< @overload */ |
|
|
|
/** |
|
* @brief Type-erased attribute value in given material layer, if exists |
|
* |
|
* Compared to @ref attribute(UnsignedInt, Containers::StringView name) const, |
|
* if @p name doesn't exist, returns @cpp nullptr @ce instead of |
|
* asserting. Expects that @p layer is smaller than @ref layerCount() const. |
|
* Cast the pointer to a concrete type based on @ref attributeType(). |
|
* @see @ref hasAttribute(), @ref attributeOr() |
|
*/ |
|
const void* findAttribute(UnsignedInt layer, Containers::StringView name) const; |
|
const void* findAttribute(UnsignedInt layer, MaterialAttribute name) const; /**< @overload */ |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
/** |
|
* @brief @copybrief findAttribute(UnsignedInt, Containers::StringView) const |
|
* @m_deprecated_since_latest Use @ref findAttribute(UnsignedInt, Containers::StringView) const |
|
* instead. |
|
*/ |
|
CORRADE_DEPRECATED("use findAttribute() instead") const void* tryAttribute(UnsignedInt layer, Containers::StringView name) const { |
|
return findAttribute(layer, name); |
|
} |
|
|
|
/** |
|
* @brief @copybrief findAttribute(UnsignedInt, MaterialAttribute) const |
|
* @m_deprecated_since_latest Use @ref findAttribute(UnsignedInt, MaterialAttribute) const |
|
* instead. |
|
*/ |
|
CORRADE_DEPRECATED("use findAttribute() instead") const void* tryAttribute(UnsignedInt layer, MaterialAttribute name) const { |
|
return findAttribute(layer, name); |
|
} |
|
#endif |
|
|
|
/** |
|
* @brief Type-erased attribute value in a named material layer, if exists |
|
* |
|
* Compared to @ref attribute(Containers::StringView, Containers::StringView name) const, |
|
* if @p name doesn't exist, returns @cpp nullptr @ce instead of |
|
* asserting. Expects that @p layer exists. Cast the pointer to a |
|
* concrete type based on @ref attributeType(). |
|
* @see @ref hasLayer(), @ref hasAttribute(), @ref attributeOr() |
|
*/ |
|
const void* findAttribute(Containers::StringView layer, Containers::StringView name) const; |
|
const void* findAttribute(Containers::StringView layer, MaterialAttribute name) const; /**< @overload */ |
|
const void* findAttribute(MaterialLayer layer, Containers::StringView name) const; /**< @overload */ |
|
const void* findAttribute(MaterialLayer layer, MaterialAttribute name) const; /**< @overload */ |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
/** |
|
* @brief @copybrief findAttribute(Containers::StringView, Containers::StringView) const |
|
* @m_deprecated_since_latest Use @ref findAttribute(Containers::StringView, Containers::StringView) const |
|
* instead. |
|
*/ |
|
CORRADE_DEPRECATED("use findAttribute() instead") const void* tryAttribute(Containers::StringView layer, Containers::StringView name) const { |
|
return findAttribute(layer, name); |
|
} |
|
|
|
/** |
|
* @brief @copybrief findAttribute(Containers::StringView, MaterialAttribute) const |
|
* @m_deprecated_since_latest Use @ref findAttribute(Containers::StringView, MaterialAttribute) const |
|
* instead. |
|
*/ |
|
CORRADE_DEPRECATED("use findAttribute() instead") const void* tryAttribute(Containers::StringView layer, MaterialAttribute name) const { |
|
return findAttribute(layer, name); |
|
} |
|
|
|
/** |
|
* @brief @copybrief findAttribute(MaterialLayer, Containers::StringView) const |
|
* @m_deprecated_since_latest Use @ref findAttribute(MaterialLayer, Containers::StringView) const |
|
* instead. |
|
*/ |
|
CORRADE_DEPRECATED("use findAttribute() instead") const void* tryAttribute(MaterialLayer layer, Containers::StringView name) const { |
|
return findAttribute(layer, name); |
|
} |
|
|
|
/** |
|
* @brief @copybrief findAttribute(MaterialLayer, MaterialAttribute) const |
|
* @m_deprecated_since_latest Use @ref findAttribute(MaterialLayer, MaterialAttribute) const |
|
* instead. |
|
*/ |
|
CORRADE_DEPRECATED("use findAttribute() instead") const void* tryAttribute(MaterialLayer layer, MaterialAttribute name) const { |
|
return findAttribute(layer, name); |
|
} |
|
#endif |
|
|
|
/** |
|
* @brief Value of a named attribute in given material layer, if exists |
|
* |
|
* Compared to @ref attribute(UnsignedInt, Containers::StringView name) const, |
|
* if @p name doesn't exist, returns |
|
* @relativeref{Corrade,Containers::NullOpt} instead of asserting. |
|
* Expects that @p layer is smaller than @ref layerCount() const and |
|
* that @p T corresponds to |
|
* @ref attributeType(UnsignedInt, Containers::StringView) const for |
|
* given @p layer and @p name. |
|
*/ |
|
template<class T> Containers::Optional<T> findAttribute(UnsignedInt layer, Containers::StringView name) const; |
|
template<class T> Containers::Optional<T> findAttribute(UnsignedInt layer, MaterialAttribute name) const; /**< @overload */ |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
/** |
|
* @brief @copybrief findAttribute(UnsignedInt, Containers::StringView) const |
|
* @m_deprecated_since_latest Use @ref findAttribute(UnsignedInt, Containers::StringView) const |
|
* instead. |
|
*/ |
|
template<class T> CORRADE_DEPRECATED("use findAttribute() instead") Containers::Optional<T> tryAttribute(UnsignedInt layer, Containers::StringView name) const { |
|
return findAttribute<T>(layer, name); |
|
} |
|
|
|
/** |
|
* @brief @copybrief findAttribute(UnsignedInt, MaterialAttribute) const |
|
* @m_deprecated_since_latest Use @ref findAttribute(UnsignedInt, MaterialAttribute) const |
|
* instead. |
|
*/ |
|
template<class T> CORRADE_DEPRECATED("use findAttribute() instead") Containers::Optional<T> tryAttribute(UnsignedInt layer, MaterialAttribute name) const { |
|
return findAttribute<T>(layer, name); |
|
} |
|
#endif |
|
|
|
/** |
|
* @brief Value of a named attribute in a named material layer, if exists |
|
* |
|
* Compared to @ref attribute(Containers::StringView, Containers::StringView name) const, |
|
* if @p name doesn't exist, returns |
|
* @relativeref{Corrade,Containers::NullOpt} instead of asserting. |
|
* Expects that @p layer exists and that @p T corresponds to |
|
* @ref attributeType(Containers::StringView, Containers::StringView) const |
|
* for given @p layer and @p name. |
|
* @see @ref hasLayer() |
|
*/ |
|
template<class T> Containers::Optional<T> findAttribute(Containers::StringView layer, Containers::StringView name) const; |
|
template<class T> Containers::Optional<T> findAttribute(Containers::StringView layer, MaterialAttribute name) const; /**< @overload */ |
|
template<class T> Containers::Optional<T> findAttribute(MaterialLayer layer, Containers::StringView name) const; /**< @overload */ |
|
template<class T> Containers::Optional<T> findAttribute(MaterialLayer layer, MaterialAttribute name) const; /**< @overload */ |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
/** |
|
* @brief @copybrief findAttribute(Containers::StringView, Containers::StringView) const |
|
* @m_deprecated_since_latest Use @ref findAttribute(Containers::StringView, Containers::StringView) const |
|
* instead. |
|
*/ |
|
template<class T> CORRADE_DEPRECATED("use findAttribute() instead") Containers::Optional<T> tryAttribute(Containers::StringView layer, Containers::StringView name) const { |
|
return findAttribute<T>(layer, name); |
|
} |
|
|
|
/** |
|
* @brief @copybrief findAttribute(Containers::StringView, MaterialAttribute) const |
|
* @m_deprecated_since_latest Use @ref findAttribute(Containers::StringView, MaterialAttribute) const |
|
* instead. |
|
*/ |
|
template<class T> CORRADE_DEPRECATED("use findAttribute() instead") Containers::Optional<T> tryAttribute(Containers::StringView layer, MaterialAttribute name) const { |
|
return findAttribute<T>(layer, name); |
|
} |
|
|
|
/** |
|
* @brief @copybrief findAttribute(UnsignedInt, Containers::StringView) const |
|
* @m_deprecated_since_latest Use @ref findAttribute(UnsignedInt, Containers::StringView) const |
|
* instead. |
|
*/ |
|
template<class T> CORRADE_DEPRECATED("use findAttribute() instead") Containers::Optional<T> tryAttribute(MaterialLayer layer, Containers::StringView name) const { |
|
return findAttribute<T>(layer, name); |
|
} |
|
|
|
/** |
|
* @brief @copybrief findAttribute(UnsignedInt, MaterialAttribute) const |
|
* @m_deprecated_since_latest Use @ref findAttribute(UnsignedInt, MaterialAttribute) const |
|
* instead. |
|
*/ |
|
template<class T> CORRADE_DEPRECATED("use findAttribute() instead") Containers::Optional<T> tryAttribute(MaterialLayer layer, MaterialAttribute name) const { |
|
return findAttribute<T>(layer, name); |
|
} |
|
#endif |
|
|
|
/** |
|
* @brief Type-erased attribute value in the base material, if exists |
|
* |
|
* Equivalent to calling @ref findAttribute(UnsignedInt, Containers::StringView) const |
|
* with @p layer set to @cpp 0 @ce. |
|
*/ |
|
const void* findAttribute(Containers::StringView name) const { |
|
return findAttribute(0, name); |
|
} |
|
const void* findAttribute(MaterialAttribute name) const { |
|
return findAttribute(0, name); |
|
} /**< @overload */ |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
/** |
|
* @brief @copybrief findAttribute(Containers::StringView) const |
|
* @m_deprecated_since_latest Use @ref findAttribute(Containers::StringView) const |
|
* instead. |
|
*/ |
|
CORRADE_DEPRECATED("use findAttribute() instead") const void* tryAttribute(Containers::StringView name) const { |
|
return findAttribute(name); |
|
} |
|
|
|
/** |
|
* @brief @copybrief findAttribute(MaterialAttribute) const |
|
* @m_deprecated_since_latest Use @ref findAttribute(MaterialAttribute) const |
|
* instead. |
|
*/ |
|
CORRADE_DEPRECATED("use findAttribute() instead") const void* tryAttribute(MaterialAttribute name) const { |
|
return findAttribute(name); |
|
} |
|
#endif |
|
|
|
/** |
|
* @brief Value of a named attribute in the base material, if exists |
|
* |
|
* Equivalent to calling @ref findAttribute(UnsignedInt, Containers::StringView) const |
|
* with @p layer set to @cpp 0 @ce. |
|
*/ |
|
template<class T> Containers::Optional<T> findAttribute(Containers::StringView name) const { |
|
return findAttribute<T>(0, name); |
|
} |
|
template<class T> Containers::Optional<T> findAttribute(MaterialAttribute name) const { |
|
return findAttribute<T>(0, name); |
|
} /**< @overload */ |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
/** |
|
* @brief @copybrief findAttribute(Containers::StringView) const |
|
* @m_deprecated_since_latest Use @ref findAttribute(Containers::StringView) const |
|
* instead. |
|
*/ |
|
template<class T> CORRADE_DEPRECATED("use findAttribute() instead") Containers::Optional<T> tryAttribute(Containers::StringView name) const { |
|
return findAttribute<T>(name); |
|
} |
|
|
|
/** |
|
* @brief @copybrief findAttribute(MaterialAttribute) const |
|
* @m_deprecated_since_latest Use @ref findAttribute(MaterialAttribute) const |
|
* instead. |
|
*/ |
|
template<class T> CORRADE_DEPRECATED("use findAttribute() instead") Containers::Optional<T> tryAttribute(MaterialAttribute name) const { |
|
return findAttribute<T>(name); |
|
} |
|
#endif |
|
|
|
/** |
|
* @brief Value of a named attribute in given layer or a default |
|
* |
|
* Compared to @ref attribute(UnsignedInt, Containers::StringView name) const, |
|
* if @p name doesn't exist, returns @p defaultValue instead of |
|
* asserting. Expects that @p layer is smaller than @ref layerCount() |
|
* const |
|
* and that @p T corresponds to @ref attributeType(UnsignedInt, Containers::StringView) const |
|
* for given @p layer and @p name. |
|
*/ |
|
template<class T> T attributeOr(UnsignedInt layer, Containers::StringView name, const T& defaultValue) const; |
|
template<class T> T attributeOr(UnsignedInt layer, MaterialAttribute name, const T& defaultValue) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Value of a named attribute in a named layer or a default |
|
* |
|
* Compared to @ref attribute(Containers::StringView, Containers::StringView name) const, |
|
* if @p name doesn't exist, returns @p defaultValue instead of |
|
* asserting. Expects that @p layer exists and that @p T corresponds to |
|
* @ref attributeType(Containers::StringView, Containers::StringView) const |
|
* for given @p layer and @p name. |
|
* @see @ref hasLayer() |
|
*/ |
|
template<class T> T attributeOr(Containers::StringView layer, Containers::StringView name, const T& defaultValue) const; |
|
template<class T> T attributeOr(Containers::StringView layer, MaterialAttribute name, const T& defaultValue) const; /**< @overload */ |
|
template<class T> T attributeOr(MaterialLayer layer, Containers::StringView name, const T& defaultValue) const; /**< @overload */ |
|
template<class T> T attributeOr(MaterialLayer layer, MaterialAttribute name, const T& defaultValue) const; /**< @overload */ |
|
|
|
/** |
|
* @brief Value of a named attribute in the base material or a default |
|
* |
|
* Equivalent to calling @ref attributeOr(UnsignedInt, Containers::StringView, const T&) const |
|
* with @p layer set to @cpp 0 @ce. |
|
*/ |
|
template<class T> T attributeOr(Containers::StringView name, const T& defaultValue) const { |
|
return attributeOr<T>(0, name, defaultValue); |
|
} |
|
template<class T> T attributeOr(MaterialAttribute name, const T& defaultValue) const { |
|
return attributeOr<T>(0, name, defaultValue); |
|
}/**< @overload */ |
|
|
|
/** |
|
* @brief Whether a material is double-sided |
|
* |
|
* Convenience access to the @ref MaterialAttribute::DoubleSided |
|
* attribute. If not present, the default is @cpp false @ce. |
|
*/ |
|
bool isDoubleSided() const; |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
/** |
|
* @brief Material flags |
|
* @m_deprecated_since_latest The flags are no longer stored directly |
|
* but generated on-the-fly from attribute data, which makes them |
|
* less efficient than calling @ref hasAttribute(), |
|
* @ref isDoubleSided() etc. |
|
* |
|
* Not all bits returned might be defined by @ref Flag, subclasses may |
|
* define extra values. |
|
*/ |
|
CORRADE_IGNORE_DEPRECATED_PUSH /* GCC warns about Flags, ugh */ |
|
CORRADE_DEPRECATED("use hasAttribute() instead") Flags flags() const; |
|
CORRADE_IGNORE_DEPRECATED_POP |
|
#endif |
|
|
|
/** |
|
* @brief Alpha mode |
|
* |
|
* Convenience access to @ref MaterialAttribute::AlphaBlend and |
|
* @ref MaterialAttribute::AlphaMask attributes. If neither is present, |
|
* the default is @ref MaterialAlphaMode::Opaque. |
|
*/ |
|
MaterialAlphaMode alphaMode() const; |
|
|
|
/** |
|
* @brief Alpha mask |
|
* |
|
* Convenience access to the @ref MaterialAttribute::AlphaMask |
|
* attribute. If not present, the default is @cpp 0.5f @ce. |
|
*/ |
|
Float alphaMask() const; |
|
|
|
/** |
|
* @brief Release layer data storage |
|
* |
|
* Releases the ownership of the layer offset array and resets internal |
|
* layer-related state to default. The material then behaves like if it |
|
* has no layers. Note that the returned array has a custom no-op |
|
* deleter when the data are not owned by the material, and while the |
|
* returned array type is mutable, the actual memory might be not. |
|
* |
|
* @attention Querying attributes after calling @ref releaseLayerData() |
|
* has undefined behavior and might lead to crashes. This is done |
|
* intentionally in order to simplify the interaction between this |
|
* function and @ref releaseAttributeData(). |
|
* @see @ref layerData(), @ref layerDataFlags() |
|
*/ |
|
Containers::Array<UnsignedInt> releaseLayerData(); |
|
|
|
/** |
|
* @brief Release attribute data storage |
|
* |
|
* Releases the ownership of the attribute array and resets internal |
|
* attribute-related state to default. The material then behaves like |
|
* if it has no attributes. Note that the returned array has a custom |
|
* no-op deleter when the data are not owned by the material, and while |
|
* the returned array type is mutable, the actual memory might be not. |
|
* |
|
* @attention Querying layers after calling @ref releaseAttributeData() |
|
* has undefined behavior and might lead to crashes. This is done |
|
* intentionally in order to simplify the interaction between this |
|
* function and @ref releaseLayerData(). |
|
* @see @ref attributeData(), @ref attributeDataFlags() |
|
*/ |
|
Containers::Array<MaterialAttributeData> releaseAttributeData(); |
|
|
|
/** |
|
* @brief Importer-specific state |
|
* |
|
* See @ref AbstractImporter::importerState() for more information. |
|
*/ |
|
const void* importerState() const { return _importerState; } |
|
|
|
private: |
|
/* For custom deleter checks. Not done in the constructors here because |
|
the restriction is pointless when used outside of plugin |
|
implementations. */ |
|
friend AbstractImporter; |
|
|
|
/* Internal helpers that don't assert, unlike layerId() / attributeId() */ |
|
UnsignedInt findLayerIdInternal(Containers::StringView layer) const; |
|
UnsignedInt layerOffset(UnsignedInt layer) const { |
|
return layer && _layerOffsets ? _layerOffsets[layer - 1] : 0; |
|
} |
|
UnsignedInt findAttributeIdInternal(UnsignedInt layer, Containers::StringView name) const; |
|
|
|
Containers::Array<MaterialAttributeData> _data; |
|
Containers::Array<UnsignedInt> _layerOffsets; |
|
MaterialTypes _types; |
|
DataFlags _attributeDataFlags, _layerDataFlags; |
|
/* 2 bytes free */ |
|
const void* _importerState; |
|
}; |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
CORRADE_IGNORE_DEPRECATED_PUSH |
|
CORRADE_ENUMSET_OPERATORS(MaterialData::Flags) |
|
|
|
/** |
|
@debugoperatorclassenum{MaterialData,MaterialData::Flag} |
|
@m_deprecated_since_latest The flags are no longer stored directly but |
|
generated on-the-fly from attribute data, which makes them less efficient |
|
than calling @ref MaterialData::hasAttribute(), |
|
@ref MaterialData::isDoubleSided() etc. |
|
*/ |
|
/* Not marked with CORRADE_DEPRECATED() as there's enough warnings already */ |
|
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, MaterialData::Flag value); |
|
|
|
/** |
|
@debugoperatorclassenum{MaterialData,MaterialData::Flags} |
|
@m_deprecated_since_latest The flags are no longer stored directly but |
|
generated on-the-fly from attribute data, which makes them less efficient |
|
than calling @ref MaterialData::hasAttribute(), |
|
@ref MaterialData::isDoubleSided() etc. |
|
*/ |
|
/* Not marked with CORRADE_DEPRECATED() as there's enough warnings already */ |
|
MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, MaterialData::Flags value); |
|
CORRADE_IGNORE_DEPRECATED_POP |
|
#endif |
|
|
|
namespace Implementation { |
|
/* LCOV_EXCL_START */ |
|
/* Has to be a struct because there can't be partial specializations for a |
|
function (which we need for pointers) */ |
|
template<class T> struct MaterialAttributeTypeFor { |
|
/* C++ why there isn't an obvious way to do such a thing?! */ |
|
static_assert(sizeof(T) == 0, "unsupported attribute type"); |
|
}; |
|
template<> struct MaterialAttributeTypeFor<bool> { |
|
constexpr static MaterialAttributeType type() { |
|
return MaterialAttributeType::Bool; |
|
} |
|
}; |
|
template<class T> struct MaterialAttributeTypeFor<const T*> { |
|
constexpr static MaterialAttributeType type() { |
|
return MaterialAttributeType::Pointer; |
|
} |
|
}; |
|
template<class T> struct MaterialAttributeTypeFor<T*> { |
|
constexpr static MaterialAttributeType type() { |
|
return MaterialAttributeType::MutablePointer; |
|
} |
|
}; |
|
/* No specialization for StringView as this type trait should not be used |
|
in that case */ |
|
template<> struct MaterialAttributeTypeFor<MaterialTextureSwizzle> { |
|
constexpr static MaterialAttributeType type() { |
|
return MaterialAttributeType::TextureSwizzle; |
|
} |
|
}; |
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
#define _c(type_) template<> struct MaterialAttributeTypeFor<type_> { \ |
|
constexpr static MaterialAttributeType type() { \ |
|
return MaterialAttributeType::type_; \ |
|
} \ |
|
}; |
|
_c(Float) |
|
_c(Deg) |
|
_c(Rad) |
|
_c(UnsignedInt) |
|
_c(Int) |
|
_c(UnsignedLong) |
|
_c(Long) |
|
_c(Vector2) |
|
_c(Vector2ui) |
|
_c(Vector2i) |
|
_c(Vector3) |
|
_c(Vector3ui) |
|
_c(Vector3i) |
|
_c(Vector4) |
|
_c(Vector4ui) |
|
_c(Vector4i) |
|
_c(Matrix2x2) |
|
_c(Matrix2x3) |
|
_c(Matrix2x4) |
|
_c(Matrix3x2) |
|
_c(Matrix3x3) |
|
_c(Matrix3x4) |
|
_c(Matrix4x2) |
|
_c(Matrix4x3) |
|
#undef _c |
|
#endif |
|
template<> struct MaterialAttributeTypeFor<Color3>: MaterialAttributeTypeFor<Vector3> {}; |
|
template<> struct MaterialAttributeTypeFor<Color4>: MaterialAttributeTypeFor<Vector4> {}; |
|
template<> struct MaterialAttributeTypeFor<Matrix3>: MaterialAttributeTypeFor<Matrix3x3> {}; |
|
/* LCOV_EXCL_STOP */ |
|
} |
|
|
|
/* The 2 extra bytes are for a null byte after the name and a type */ |
|
template<class T |
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
, class |
|
#endif |
|
> constexpr MaterialAttributeData::MaterialAttributeData(const Containers::StringView name, const T& value) noexcept: |
|
_data{Implementation::MaterialAttributeTypeFor<T>::type(), ( |
|
/* It would sort before " LayerName" and that's not desirable */ |
|
CORRADE_CONSTEXPR_ASSERT(!name.isEmpty(), "Trade::MaterialAttributeData: name is not allowed to be empty"), |
|
/* MSVC 2015 complains about "error C2065: 'T': undeclared identifier" |
|
in the lambda inside this macro. Sorry, the assert will be less |
|
useful on that stupid thing. */ |
|
#ifndef CORRADE_MSVC2015_COMPATIBILITY |
|
CORRADE_CONSTEXPR_ASSERT(name.size() + sizeof(T) + 2 <= Implementation::MaterialAttributeDataSize, "Trade::MaterialAttributeData: name" << name << "too long, expected at most" << Implementation::MaterialAttributeDataSize - sizeof(T) - 2 << "bytes for" << Implementation::MaterialAttributeTypeFor<T>::type() << "but got" << name.size()), |
|
#else |
|
CORRADE_CONSTEXPR_ASSERT(name.size() + sizeof(T) + 2 <= Implementation::MaterialAttributeDataSize, "Trade::MaterialAttributeData: name" << name << "too long, got" << name.size() << "bytes"), |
|
#endif |
|
name), value} {} |
|
|
|
/* The 4 extra bytes are for a null byte after both the name and value, a type |
|
and a string size */ |
|
constexpr MaterialAttributeData::MaterialAttributeData(const Containers::StringView name, const Containers::StringView value) noexcept: _data{( |
|
/* It would sort before " LayerName" and that's not desirable */ |
|
CORRADE_CONSTEXPR_ASSERT(!name.isEmpty(), "Trade::MaterialAttributeData: name is not allowed to be empty"), |
|
CORRADE_CONSTEXPR_ASSERT(name.size() + value.size() + 4 <= Implementation::MaterialAttributeDataSize, "Trade::MaterialAttributeData: name" << name << "and value" << value << "too long, expected at most" << Implementation::MaterialAttributeDataSize - 4 << "bytes in total but got" << name.size() + value.size()), |
|
name), value} {} |
|
|
|
template<class T> T MaterialAttributeData::value() const { |
|
CORRADE_ASSERT(Implementation::MaterialAttributeTypeFor<T>::type() == _data.type, |
|
"Trade::MaterialAttributeData::value():" << (_data.data + 1) << "is" << _data.type << "but requested a type equivalent to" << Implementation::MaterialAttributeTypeFor<T>::type(), {}); |
|
return *reinterpret_cast<const T*>(value()); |
|
} |
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
template<> Containers::StringView MaterialAttributeData::value<Containers::StringView>() const; |
|
template<> Containers::ArrayView<const void> MaterialAttributeData::value<Containers::ArrayView<const void>>() const; |
|
#endif |
|
|
|
template<class T> T MaterialData::attribute(const UnsignedInt layer, const UnsignedInt id) const { |
|
const void* const value = attribute(layer, id); |
|
#ifdef CORRADE_GRACEFUL_ASSERT |
|
if(!value) return {}; |
|
#endif |
|
#ifndef CORRADE_NO_ASSERT |
|
const Trade::MaterialAttributeData& data = _data[layerOffset(layer) + id]; |
|
#endif |
|
CORRADE_ASSERT(Implementation::MaterialAttributeTypeFor<T>::type() == data._data.type, |
|
"Trade::MaterialData::attribute():" << (data._data.data + 1) << "is" << data._data.type << "but requested a type equivalent to" << Implementation::MaterialAttributeTypeFor<T>::type(), {}); |
|
return *reinterpret_cast<const T*>(value); |
|
} |
|
|
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type MaterialData::mutableAttribute(const UnsignedInt layer, const UnsignedInt id) { |
|
void* const value = mutableAttribute(layer, id); |
|
#ifdef CORRADE_GRACEFUL_ASSERT |
|
if(!value) return *reinterpret_cast<T*>(this); |
|
#endif |
|
#ifndef CORRADE_NO_ASSERT |
|
const Trade::MaterialAttributeData& data = _data[layerOffset(layer) + id]; |
|
#endif |
|
CORRADE_ASSERT(Implementation::MaterialAttributeTypeFor<T>::type() == data._data.type, |
|
"Trade::MaterialData::mutableAttribute():" << (data._data.data + 1) << "is" << data._data.type << "but requested a type equivalent to" << Implementation::MaterialAttributeTypeFor<T>::type(), *reinterpret_cast<T*>(this)); |
|
return *reinterpret_cast<T*>(value); |
|
} |
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
template<> Containers::StringView MaterialData::attribute<Containers::StringView>(UnsignedInt, UnsignedInt) const; |
|
template<> Containers::MutableStringView MaterialData::mutableAttribute<Containers::MutableStringView>(UnsignedInt, UnsignedInt); |
|
template<> Containers::ArrayView<const void> MaterialData::attribute<Containers::ArrayView<const void>>(UnsignedInt, UnsignedInt) const; |
|
template<> Containers::ArrayView<void> MaterialData::mutableAttribute<Containers::ArrayView<void>>(UnsignedInt, UnsignedInt); |
|
#endif |
|
|
|
template<class T> T MaterialData::attribute(const UnsignedInt layer, const Containers::StringView name) const { |
|
CORRADE_ASSERT(layer < layerCount(), |
|
"Trade::MaterialData::attribute(): index" << layer << "out of range for" << layerCount() << "layers", {}); |
|
const UnsignedInt id = findAttributeIdInternal(layer, name); |
|
CORRADE_ASSERT(id != ~UnsignedInt{}, |
|
"Trade::MaterialData::attribute(): attribute" << name << "not found in layer" << layer, {}); |
|
return attribute<T>(layer, id); |
|
} |
|
|
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type MaterialData::mutableAttribute(const UnsignedInt layer, const Containers::StringView name) { |
|
CORRADE_ASSERT(layer < layerCount(), |
|
"Trade::MaterialData::mutableAttribute(): index" << layer << "out of range for" << layerCount() << "layers", *reinterpret_cast<T*>(this)); |
|
const UnsignedInt id = findAttributeIdInternal(layer, name); |
|
CORRADE_ASSERT(id != ~UnsignedInt{}, |
|
"Trade::MaterialData::mutableAttribute(): attribute" << name << "not found in layer" << layer, *reinterpret_cast<T*>(this)); |
|
return mutableAttribute<T>(layer, id); |
|
} |
|
|
|
template<class T> T MaterialData::attribute(const UnsignedInt layer, const MaterialAttribute name) const { |
|
const Containers::StringView string = Implementation::materialAttributeNameInternal(name); |
|
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << name, {}); |
|
return attribute<T>(layer, string); |
|
} |
|
|
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type MaterialData::mutableAttribute(const UnsignedInt layer, const MaterialAttribute name) { |
|
const Containers::StringView string = Implementation::materialAttributeNameInternal(name); |
|
CORRADE_ASSERT(string.data(), "Trade::MaterialData::mutableAttribute(): invalid name" << name, *reinterpret_cast<T*>(this)); |
|
return mutableAttribute<T>(layer, string); |
|
} |
|
|
|
template<class T> T MaterialData::attribute(const Containers::StringView layer, const UnsignedInt id) const { |
|
const UnsignedInt layerId = findLayerIdInternal(layer); |
|
CORRADE_ASSERT(layerId != ~UnsignedInt{}, |
|
"Trade::MaterialData::attribute(): layer" << layer << "not found", {}); |
|
CORRADE_ASSERT(id < attributeCount(layer), |
|
"Trade::MaterialData::attribute(): index" << id << "out of range for" << attributeCount(layer) << "attributes in layer" << layer, {}); |
|
return attribute<T>(layerId, id); |
|
} |
|
|
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type MaterialData::mutableAttribute(const Containers::StringView layer, const UnsignedInt id) { |
|
const UnsignedInt layerId = findLayerIdInternal(layer); |
|
CORRADE_ASSERT(layerId != ~UnsignedInt{}, |
|
"Trade::MaterialData::mutableAttribute(): layer" << layer << "not found", *reinterpret_cast<T*>(this)); |
|
CORRADE_ASSERT(id < attributeCount(layer), |
|
"Trade::MaterialData::mutableAttribute(): index" << id << "out of range for" << attributeCount(layer) << "attributes in layer" << layer, *reinterpret_cast<T*>(this)); |
|
return mutableAttribute<T>(layerId, id); |
|
} |
|
|
|
template<class T> T MaterialData::attribute(const Containers::StringView layer, const Containers::StringView name) const { |
|
const UnsignedInt layerId = findLayerIdInternal(layer); |
|
CORRADE_ASSERT(layerId != ~UnsignedInt{}, |
|
"Trade::MaterialData::attribute(): layer" << layer << "not found", {}); |
|
const UnsignedInt id = findAttributeIdInternal(layerId, name); |
|
CORRADE_ASSERT(id != ~UnsignedInt{}, |
|
"Trade::MaterialData::attribute(): attribute" << name << "not found in layer" << layer, {}); |
|
return attribute<T>(layerId, id); |
|
} |
|
|
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type MaterialData::mutableAttribute(const Containers::StringView layer, const Containers::StringView name) { |
|
const UnsignedInt layerId = findLayerIdInternal(layer); |
|
CORRADE_ASSERT(layerId != ~UnsignedInt{}, |
|
"Trade::MaterialData::mutableAttribute(): layer" << layer << "not found", *reinterpret_cast<T*>(this)); |
|
const UnsignedInt id = findAttributeIdInternal(layerId, name); |
|
CORRADE_ASSERT(id != ~UnsignedInt{}, |
|
"Trade::MaterialData::mutableAttribute(): attribute" << name << "not found in layer" << layer, *reinterpret_cast<T*>(this)); |
|
return mutableAttribute<T>(layerId, id); |
|
} |
|
|
|
template<class T> T MaterialData::attribute(const Containers::StringView layer, const MaterialAttribute name) const { |
|
const Containers::StringView string = Implementation::materialAttributeNameInternal(name); |
|
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << name, {}); |
|
return attribute<T>(layer, string); |
|
} |
|
|
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type MaterialData::mutableAttribute(const Containers::StringView layer, const MaterialAttribute name) { |
|
const Containers::StringView string = Implementation::materialAttributeNameInternal(name); |
|
CORRADE_ASSERT(string.data(), "Trade::MaterialData::mutableAttribute(): invalid name" << name, *reinterpret_cast<T*>(this)); |
|
return mutableAttribute<T>(layer, string); |
|
} |
|
|
|
template<class T> T MaterialData::attribute(const MaterialLayer layer, const UnsignedInt id) const { |
|
const Containers::StringView string = Implementation::materialLayerNameInternal(layer); |
|
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << layer, {}); |
|
return attribute<T>(string, id); |
|
} |
|
|
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type MaterialData::mutableAttribute(const MaterialLayer layer, const UnsignedInt id) { |
|
const Containers::StringView string = Implementation::materialLayerNameInternal(layer); |
|
CORRADE_ASSERT(string.data(), "Trade::MaterialData::mutableAttribute(): invalid name" << layer, *reinterpret_cast<T*>(this)); |
|
return mutableAttribute<T>(string, id); |
|
} |
|
|
|
template<class T> T MaterialData::attribute(const MaterialLayer layer, const Containers::StringView name) const { |
|
const Containers::StringView string = Implementation::materialLayerNameInternal(layer); |
|
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << layer, {}); |
|
return attribute<T>(string, name); |
|
} |
|
|
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type MaterialData::mutableAttribute(const MaterialLayer layer, const Containers::StringView name) { |
|
const Containers::StringView string = Implementation::materialLayerNameInternal(layer); |
|
CORRADE_ASSERT(string.data(), "Trade::MaterialData::mutableAttribute(): invalid name" << layer, *reinterpret_cast<T*>(this)); |
|
return mutableAttribute<T>(string, name); |
|
} |
|
|
|
template<class T> T MaterialData::attribute(const MaterialLayer layer, const MaterialAttribute name) const { |
|
const Containers::StringView string = Implementation::materialLayerNameInternal(layer); |
|
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attribute(): invalid name" << layer, {}); |
|
return attribute<T>(string, name); |
|
} |
|
|
|
template<class T> typename std::conditional<std::is_same<T, Containers::MutableStringView>::value || std::is_same<T, Containers::ArrayView<void>>::value, T, T&>::type MaterialData::mutableAttribute(const MaterialLayer layer, const MaterialAttribute name) { |
|
const Containers::StringView string = Implementation::materialLayerNameInternal(layer); |
|
CORRADE_ASSERT(string.data(), "Trade::MaterialData::mutableAttribute(): invalid name" << layer, *reinterpret_cast<T*>(this)); |
|
return mutableAttribute<T>(string, name); |
|
} |
|
|
|
template<class T> Containers::Optional<T> MaterialData::findAttribute(const UnsignedInt layer, const Containers::StringView name) const { |
|
CORRADE_ASSERT(layer < layerCount(), |
|
"Trade::MaterialData::findAttribute(): index" << layer << "out of range for" << layerCount() << "layers", {}); |
|
const UnsignedInt id = findAttributeIdInternal(layer, name); |
|
if(id == ~UnsignedInt{}) return {}; |
|
return attribute<T>(layer, id); |
|
} |
|
|
|
template<class T> Containers::Optional<T> MaterialData::findAttribute(const UnsignedInt layer, const MaterialAttribute name) const { |
|
const Containers::StringView string = Implementation::materialAttributeNameInternal(name); |
|
CORRADE_ASSERT(string.data(), "Trade::MaterialData::findAttribute(): invalid name" << name, {}); |
|
return findAttribute<T>(layer, string); |
|
} |
|
|
|
template<class T> Containers::Optional<T> MaterialData::findAttribute(const Containers::StringView layer, const Containers::StringView name) const { |
|
const UnsignedInt layerId = findLayerIdInternal(layer); |
|
CORRADE_ASSERT(layerId != ~UnsignedInt{}, |
|
"Trade::MaterialData::findAttribute(): layer" << layer << "not found", {}); |
|
return findAttribute<T>(layerId, name); |
|
} |
|
|
|
template<class T> Containers::Optional<T> MaterialData::findAttribute(const Containers::StringView layer, const MaterialAttribute name) const { |
|
const Containers::StringView string = Implementation::materialAttributeNameInternal(name); |
|
CORRADE_ASSERT(string.data(), "Trade::MaterialData::findAttribute(): invalid name" << name, {}); |
|
return findAttribute<T>(layer, string); |
|
} |
|
|
|
template<class T> Containers::Optional<T> MaterialData::findAttribute(const MaterialLayer layer, const Containers::StringView name) const { |
|
const Containers::StringView string = Implementation::materialLayerNameInternal(layer); |
|
CORRADE_ASSERT(string.data(), "Trade::MaterialData::findAttribute(): invalid name" << layer, {}); |
|
return findAttribute<T>(string, name); |
|
} |
|
|
|
template<class T> Containers::Optional<T> MaterialData::findAttribute(const MaterialLayer layer, const MaterialAttribute name) const { |
|
const Containers::StringView string = Implementation::materialLayerNameInternal(layer); |
|
CORRADE_ASSERT(string.data(), "Trade::MaterialData::findAttribute(): invalid name" << layer, {}); |
|
return findAttribute<T>(string, name); |
|
} |
|
|
|
template<class T> T MaterialData::attributeOr(const UnsignedInt layer, const Containers::StringView name, const T& defaultValue) const { |
|
CORRADE_ASSERT(layer < layerCount(), |
|
"Trade::MaterialData::attributeOr(): index" << layer << "out of range for" << layerCount() << "layers", {}); |
|
const UnsignedInt id = findAttributeIdInternal(layer, name); |
|
if(id == ~UnsignedInt{}) return defaultValue; |
|
return attribute<T>(layer, id); |
|
} |
|
|
|
template<class T> T MaterialData::attributeOr(const UnsignedInt layer, const MaterialAttribute name, const T& defaultValue) const { |
|
const Containers::StringView string = Implementation::materialAttributeNameInternal(name); |
|
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attributeOr(): invalid name" << name, {}); |
|
return attributeOr<T>(layer, string, defaultValue); |
|
} |
|
|
|
template<class T> T MaterialData::attributeOr(const Containers::StringView layer, const Containers::StringView name, const T& defaultValue) const { |
|
const UnsignedInt layerId = findLayerIdInternal(layer); |
|
CORRADE_ASSERT(layerId != ~UnsignedInt{}, |
|
"Trade::MaterialData::attributeOr(): layer" << layer << "not found", {}); |
|
return attributeOr<T>(layerId, name, defaultValue); |
|
} |
|
|
|
template<class T> T MaterialData::attributeOr(const Containers::StringView layer, const MaterialAttribute name, const T& defaultValue) const { |
|
const Containers::StringView string = Implementation::materialAttributeNameInternal(name); |
|
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attributeOr(): invalid name" << name, {}); |
|
return attributeOr<T>(layer, string, defaultValue); |
|
} |
|
|
|
template<class T> T MaterialData::attributeOr(const MaterialLayer layer, const Containers::StringView name, const T& defaultValue) const { |
|
const Containers::StringView string = Implementation::materialLayerNameInternal(layer); |
|
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attributeOr(): invalid name" << layer, {}); |
|
return attributeOr<T>(string, name, defaultValue); |
|
} |
|
|
|
template<class T> T MaterialData::attributeOr(const MaterialLayer layer, const MaterialAttribute name, const T& defaultValue) const { |
|
const Containers::StringView string = Implementation::materialLayerNameInternal(layer); |
|
CORRADE_ASSERT(string.data(), "Trade::MaterialData::attributeOr(): invalid name" << layer, {}); |
|
return attributeOr<T>(string, name, defaultValue); |
|
} |
|
|
|
}} |
|
|
|
#endif
|
|
|