Browse Source

MaterialTools: use filter() and merge() in phongToPbrMetallicRoughness().

Nice and tidy. I like that.
pull/601/head
Vladimír Vondruš 3 years ago
parent
commit
ff7a304b57
  1. 64
      src/Magnum/MaterialTools/PhongToPbrMetallicRoughness.cpp

64
src/Magnum/MaterialTools/PhongToPbrMetallicRoughness.cpp

@ -26,11 +26,14 @@
#include "PhongToPbrMetallicRoughness.h" #include "PhongToPbrMetallicRoughness.h"
#include <Corrade/Containers/BitArray.h> #include <Corrade/Containers/BitArray.h>
#include <Corrade/Containers/BitArrayView.h>
#include <Corrade/Containers/GrowableArray.h> #include <Corrade/Containers/GrowableArray.h>
#include <Corrade/Containers/String.h> #include <Corrade/Containers/String.h>
#include "Magnum/Math/Matrix3.h" #include "Magnum/Math/Matrix3.h"
#include "Magnum/Math/Vector4.h" #include "Magnum/Math/Vector4.h"
#include "Magnum/MaterialTools/Filter.h"
#include "Magnum/MaterialTools/Merge.h"
#include "Magnum/Trade/MaterialData.h" #include "Magnum/Trade/MaterialData.h"
namespace Magnum { namespace MaterialTools { namespace Magnum { namespace MaterialTools {
@ -38,13 +41,13 @@ namespace Magnum { namespace MaterialTools {
using namespace Containers::Literals; using namespace Containers::Literals;
Containers::Optional<Trade::MaterialData> phongToPbrMetallicRoughness(const Trade::MaterialData& material, const PhongToPbrMetallicRoughnessFlags flags) { Containers::Optional<Trade::MaterialData> phongToPbrMetallicRoughness(const Trade::MaterialData& material, const PhongToPbrMetallicRoughnessFlags flags) {
/* Output attributes, reserve assuming some input attributes will get /* Attributes to merge into the base layer. We'll need at most 5 -- color,
replaced with different */ texture and texture layer/coordinates/matrix. */
Containers::Array<Trade::MaterialAttributeData> attributes; Containers::Array<Trade::MaterialAttributeData> attributes;
arrayReserve(attributes, material.attributeData().size()); arrayReserve(attributes, 5);
/* Attributes to skip in the base layer */ /* Attributes to keep */
Containers::BitArray attributesToSkip{ValueInit, material.attributeCount(0)}; Containers::BitArray attributesToKeep{DirectInit, material.attributeDataOffset(material.layerCount()), true};
/* Decide about unconvertable attributes */ /* Decide about unconvertable attributes */
/** @todo conversion of these: /** @todo conversion of these:
@ -67,7 +70,7 @@ Containers::Optional<Trade::MaterialData> phongToPbrMetallicRoughness(const Trad
Warning{} << "MaterialTools::phongToPbrMetallicRoughness(): unconvertable" << attribute << "attribute, skipping"; Warning{} << "MaterialTools::phongToPbrMetallicRoughness(): unconvertable" << attribute << "attribute, skipping";
if(flags >= PhongToPbrMetallicRoughnessFlag::DropUnconvertableAttributes) if(flags >= PhongToPbrMetallicRoughnessFlag::DropUnconvertableAttributes)
attributesToSkip.set(*id); attributesToKeep.reset(*id);
} }
for(const Trade::MaterialAttribute attribute: { for(const Trade::MaterialAttribute attribute: {
Trade::MaterialAttribute::AmbientTexture, Trade::MaterialAttribute::AmbientTexture,
@ -87,13 +90,13 @@ Containers::Optional<Trade::MaterialData> phongToPbrMetallicRoughness(const Trad
Warning{} << "MaterialTools::phongToPbrMetallicRoughness(): unconvertable" << attribute << "attribute, skipping"; Warning{} << "MaterialTools::phongToPbrMetallicRoughness(): unconvertable" << attribute << "attribute, skipping";
if(flags >= PhongToPbrMetallicRoughnessFlag::DropUnconvertableAttributes) { if(flags >= PhongToPbrMetallicRoughnessFlag::DropUnconvertableAttributes) {
attributesToSkip.set(*id); attributesToKeep.reset(*id);
if(matrixId) if(matrixId)
attributesToSkip.set(*matrixId); attributesToKeep.reset(*matrixId);
if(coordinatesId) if(coordinatesId)
attributesToSkip.set(*coordinatesId); attributesToKeep.reset(*coordinatesId);
if(layerId) if(layerId)
attributesToSkip.set(*layerId); attributesToKeep.reset(*layerId);
} }
} }
@ -105,7 +108,7 @@ Containers::Optional<Trade::MaterialData> phongToPbrMetallicRoughness(const Trad
/* Skip unless we're told to keep the original attributes */ /* Skip unless we're told to keep the original attributes */
if(!(flags >= PhongToPbrMetallicRoughnessFlag::KeepOriginalAttributes)) if(!(flags >= PhongToPbrMetallicRoughnessFlag::KeepOriginalAttributes))
attributesToSkip.set(*id); attributesToKeep.reset(*id);
} }
/* Diffuse texture and related attributes */ /* Diffuse texture and related attributes */
@ -127,40 +130,23 @@ Containers::Optional<Trade::MaterialData> phongToPbrMetallicRoughness(const Trad
/* Skip unless we're told to keep the original attributes */ /* Skip unless we're told to keep the original attributes */
if(!(flags >= PhongToPbrMetallicRoughnessFlag::KeepOriginalAttributes)) { if(!(flags >= PhongToPbrMetallicRoughnessFlag::KeepOriginalAttributes)) {
attributesToSkip.set(*id); attributesToKeep.reset(*id);
if(matrixId) if(matrixId)
attributesToSkip.set(*matrixId); attributesToKeep.reset(*matrixId);
if(coordinatesId) if(coordinatesId)
attributesToSkip.set(*coordinatesId); attributesToKeep.reset(*coordinatesId);
if(layerId) if(layerId)
attributesToSkip.set(*layerId); attributesToKeep.reset(*layerId);
} }
} }
/* New layer offsets. If there's no layer data in the original, the whole /* Filter & merge the attributes -- they have to be moved into the
attribute array is the base layer */ constructor in order to get sorted. Remove the Phong type from the
Containers::Array<UnsignedInt> layers; output as well. There should be no conflicts if we did everything above
if(material.layerData()) { correctly, so just unpack the Optional directly. */
/* Calculate the difference in base layer size */ return *CORRADE_INTERNAL_ASSERT_EXPRESSION(merge(
Int baseLayerSizeDifference = attributes.size(); filterAttributes(material, attributesToKeep, ~Trade::MaterialType::Phong),
/** @todo have popcount() on BitArray */ Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness, std::move(attributes)}));
for(std::size_t i = 0; i != attributesToSkip.size(); ++i)
if(attributesToSkip[i]) --baseLayerSizeDifference;
/* Fill the new layer offset array */
layers = Containers::Array<UnsignedInt>{NoInit, material.layerData().size()};
for(std::size_t i = 0; i != layers.size(); ++i)
layers[i] = material.layerData()[i] + baseLayerSizeDifference;
}
/* Add the remaining attribute data including the extra layers, except ones
that are meant to be skipped in the base layer */
for(std::size_t i = 0; i != material.attributeData().size(); ++i)
if(i >= attributesToSkip.size() || !attributesToSkip[i])
arrayAppend(attributes, material.attributeData()[i]);
/* Replace Phong with PbrMetallicRoughness in the output */
return Trade::MaterialData{(material.types() & ~Trade::MaterialType::Phong)|Trade::MaterialType::PbrMetallicRoughness, std::move(attributes), std::move(layers)};
} }
}} }}

Loading…
Cancel
Save