mirror of https://github.com/mosra/magnum.git
Browse Source
Now that there will be a whole new MaterialTools library, I really need this helper.pull/605/head
10 changed files with 930 additions and 8 deletions
@ -0,0 +1,69 @@ |
|||||||
|
/*
|
||||||
|
This file is part of Magnum. |
||||||
|
|
||||||
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
||||||
|
2020, 2021, 2022 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <Corrade/TestSuite/Tester.h> |
||||||
|
|
||||||
|
#include "Magnum/Math/Color.h" |
||||||
|
#include "Magnum/Trade/MaterialData.h" |
||||||
|
#include "Magnum/DebugTools/CompareMaterial.h" |
||||||
|
|
||||||
|
using namespace Magnum; |
||||||
|
|
||||||
|
#define DOXYGEN_ELLIPSIS(...) __VA_ARGS__ |
||||||
|
|
||||||
|
struct MaterialTest: TestSuite::Tester { |
||||||
|
explicit MaterialTest(); |
||||||
|
|
||||||
|
void conversion(); |
||||||
|
}; |
||||||
|
|
||||||
|
MaterialTest::MaterialTest() { |
||||||
|
addTests({&MaterialTest::conversion}); |
||||||
|
} |
||||||
|
|
||||||
|
void MaterialTest::conversion() { |
||||||
|
Trade::MaterialData actual{Trade::MaterialType::PbrClearCoat|Trade::MaterialType::PbrMetallicRoughness, { |
||||||
|
{Trade::MaterialAttribute::BaseColor, Color4{0.851206f, 0.687386f, 0.416013f}}, |
||||||
|
{Trade::MaterialAttribute::Metalness, 0.603401f}, |
||||||
|
{Trade::MaterialAttribute::Roughness, 0.105112f}, |
||||||
|
{Trade::MaterialAttribute::DoubleSided, true}, |
||||||
|
{Trade::MaterialLayer::ClearCoat}, |
||||||
|
{Trade::MaterialAttribute::LayerFactor, 0.02f}, |
||||||
|
{Trade::MaterialAttribute::Roughness, 0.320856f}, |
||||||
|
}, {4, 7}}; |
||||||
|
|
||||||
|
Trade::MaterialData expected{Trade::MaterialType::PbrMetallicRoughness, { |
||||||
|
{Trade::MaterialAttribute::BaseColor, Color4{0.851206f, 0.687386f, 0.416013f}}, |
||||||
|
{Trade::MaterialAttribute::Metalness, 0.603401f}, |
||||||
|
{Trade::MaterialAttribute::Roughness, 0.105112f}, |
||||||
|
{Trade::MaterialAttribute::DoubleSided, false} |
||||||
|
}}; |
||||||
|
|
||||||
|
/* [usage] */ |
||||||
|
CORRADE_COMPARE_AS(actual, expected, DebugTools::CompareMaterial); |
||||||
|
/* [usage] */ |
||||||
|
} |
||||||
|
|
||||||
|
CORRADE_TEST_MAIN(MaterialTest) |
||||||
@ -0,0 +1,395 @@ |
|||||||
|
/*
|
||||||
|
This file is part of Magnum. |
||||||
|
|
||||||
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
||||||
|
2020, 2021, 2022 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "CompareMaterial.h" |
||||||
|
|
||||||
|
#include <Corrade/Containers/Array.h> |
||||||
|
#include <Corrade/Containers/GrowableArray.h> |
||||||
|
#include <Corrade/Containers/Triple.h> |
||||||
|
#include <Corrade/Utility/Math.h> /* max() that works with enums */ |
||||||
|
#include <Corrade/TestSuite/Comparator.h> |
||||||
|
|
||||||
|
#include "Magnum/Math/Matrix.h" |
||||||
|
#include "Magnum/Math/Vector4.h" |
||||||
|
#include "Magnum/Trade/MaterialData.h" |
||||||
|
|
||||||
|
namespace Corrade { namespace TestSuite { |
||||||
|
|
||||||
|
using namespace Magnum; |
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
/* Higher values mean bigger change */ |
||||||
|
enum class MaterialState { |
||||||
|
Same, |
||||||
|
DifferentTypes, |
||||||
|
DifferentAttributeValues, |
||||||
|
DifferentAttributeTypes, |
||||||
|
DifferentAttributes, |
||||||
|
DifferentLayers |
||||||
|
}; |
||||||
|
|
||||||
|
enum class AttributeState { |
||||||
|
Same, |
||||||
|
DifferentValue, |
||||||
|
DifferentType, |
||||||
|
OnlyInExpected, |
||||||
|
OnlyInActual |
||||||
|
}; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
struct Comparator<DebugTools::CompareMaterial>::State { |
||||||
|
MaterialState materialState = MaterialState::Same; |
||||||
|
|
||||||
|
/* Second is attribute ID in the actual material (unless AttributeState is
|
||||||
|
OnlyInExpected), third is attribute ID in the expected material (unless |
||||||
|
AttributeState is OnlyInActual). */ |
||||||
|
Containers::Array<Containers::Triple<AttributeState, UnsignedInt, UnsignedInt>> attributes; |
||||||
|
/* Offsets into the attributes array for each layer. I.e., layer i is
|
||||||
|
stored in `attributes[layerOffsets[i]]` to |
||||||
|
`attributes[layerOffsets[i + 1]]`. */ |
||||||
|
Containers::Array<UnsignedInt> layerOffsets; |
||||||
|
|
||||||
|
const Trade::MaterialData* actual{}; |
||||||
|
const Trade::MaterialData* expected{}; |
||||||
|
}; |
||||||
|
|
||||||
|
Comparator<DebugTools::CompareMaterial>::Comparator(): _state{InPlaceInit} {} |
||||||
|
|
||||||
|
Comparator<DebugTools::CompareMaterial>::~Comparator() = default; |
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
bool attributesEqual(const Trade::MaterialAttributeData& a, const Trade::MaterialAttributeData& b) { |
||||||
|
#ifdef CORRADE_TARGET_GCC |
||||||
|
#pragma GCC diagnostic push |
||||||
|
#pragma GCC diagnostic error "-Wswitch" |
||||||
|
#endif |
||||||
|
CORRADE_INTERNAL_ASSERT(a.type() == b.type()); |
||||||
|
switch(a.type()) { |
||||||
|
#define _c(type) case Trade::MaterialAttributeType::type: \ |
||||||
|
return a.value<type>() == b.value<type>(); |
||||||
|
#define _ct(name, type) case Trade::MaterialAttributeType::name: \ |
||||||
|
return a.value<type>() == b.value<type>(); |
||||||
|
_ct(Bool, bool) |
||||||
|
/* LCOV_EXCL_START */ |
||||||
|
_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) |
||||||
|
/* LCOV_EXCL_STOP */ |
||||||
|
_ct(Pointer, const void*) |
||||||
|
_ct(MutablePointer, void*) |
||||||
|
_ct(String, Containers::StringView) |
||||||
|
_ct(TextureSwizzle, Trade::MaterialTextureSwizzle) |
||||||
|
#undef _c |
||||||
|
#undef _ct |
||||||
|
case Trade::MaterialAttributeType::Buffer: |
||||||
|
return Containers::StringView{Containers::arrayCast<const char>(a.value<Containers::ArrayView<const void>>())} == Containers::StringView{Containers::arrayCast<const char>(b.value<Containers::ArrayView<const void>>())}; |
||||||
|
} |
||||||
|
#ifdef CORRADE_TARGET_GCC |
||||||
|
#pragma GCC diagnostic pop |
||||||
|
#endif |
||||||
|
|
||||||
|
CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
TestSuite::ComparisonStatusFlags Comparator<DebugTools::CompareMaterial>::operator()(const Trade::MaterialData& actual, const Trade::MaterialData& expected) { |
||||||
|
_state->actual = &actual; |
||||||
|
_state->expected = &expected; |
||||||
|
|
||||||
|
if(actual.types() != expected.types()) |
||||||
|
_state->materialState = MaterialState::DifferentTypes; |
||||||
|
|
||||||
|
/* The layer offset array has one extra item for the last layer count */ |
||||||
|
const std::size_t layerMax = Math::max(actual.layerCount(), expected.layerCount()); |
||||||
|
_state->layerOffsets = Containers::Array<UnsignedInt>{NoInit, layerMax + 1}; |
||||||
|
|
||||||
|
/* Go over all layers that are in both materials */ |
||||||
|
std::size_t layer = 0; |
||||||
|
for(const std::size_t layerMin = Math::min(actual.layerCount(), expected.layerCount()); layer != layerMin; ++layer) { |
||||||
|
_state->layerOffsets[layer] = _state->attributes.size(); |
||||||
|
UnsignedInt inActual = 0; |
||||||
|
UnsignedInt inExpected = 0; |
||||||
|
|
||||||
|
/* Take the earliest-sorted attribute from either material */ |
||||||
|
while(inActual != actual.attributeCount(layer) && inExpected != expected.attributeCount(layer)) { |
||||||
|
if(actual.attributeName(layer, inActual) == expected.attributeName(layer, inExpected)) { |
||||||
|
AttributeState attributeState; |
||||||
|
if(actual.attributeType(layer, inActual) != expected.attributeType(layer, inExpected)) { |
||||||
|
attributeState = AttributeState::DifferentType; |
||||||
|
_state->materialState = Utility::max(_state->materialState, MaterialState::DifferentAttributeTypes); |
||||||
|
} else if(!attributesEqual(actual.attributeData(layer, inActual), expected.attributeData(layer, inExpected))) { |
||||||
|
attributeState = AttributeState::DifferentValue; |
||||||
|
_state->materialState = Utility::max(_state->materialState, MaterialState::DifferentAttributeValues); |
||||||
|
} else { |
||||||
|
attributeState = AttributeState::Same; |
||||||
|
} |
||||||
|
|
||||||
|
arrayAppend(_state->attributes, InPlaceInit, attributeState, inActual, inExpected); |
||||||
|
++inActual; |
||||||
|
++inExpected; |
||||||
|
} else if(actual.attributeName(inActual) < expected.attributeName(inExpected)) { |
||||||
|
arrayAppend(_state->attributes, InPlaceInit, AttributeState::OnlyInActual, inActual, ~UnsignedInt{}); |
||||||
|
_state->materialState = Utility::max(_state->materialState, MaterialState::DifferentAttributes); |
||||||
|
++inActual; |
||||||
|
} else if(actual.attributeName(inActual) > expected.attributeName(inExpected)) { |
||||||
|
arrayAppend(_state->attributes, InPlaceInit, AttributeState::OnlyInExpected, ~UnsignedInt{}, inExpected); |
||||||
|
_state->materialState = Utility::max(_state->materialState, MaterialState::DifferentAttributes); |
||||||
|
++inExpected; |
||||||
|
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ |
||||||
|
} |
||||||
|
|
||||||
|
/* Consume remaining leftover attributes in either. Only one of these
|
||||||
|
loops get entered. */ |
||||||
|
while(inActual < actual.attributeCount(layer)) { |
||||||
|
arrayAppend(_state->attributes, InPlaceInit, AttributeState::OnlyInActual, inActual, ~UnsignedInt{}); |
||||||
|
_state->materialState = Utility::max(_state->materialState, MaterialState::DifferentAttributes); |
||||||
|
++inActual; |
||||||
|
} |
||||||
|
while(inExpected < expected.attributeCount(layer)) { |
||||||
|
arrayAppend(_state->attributes, InPlaceInit, AttributeState::OnlyInExpected, ~UnsignedInt{}, inExpected); |
||||||
|
_state->materialState = Utility::max(_state->materialState, MaterialState::DifferentAttributes); |
||||||
|
++inExpected; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Go over remaining actual/expected layers which weren't in
|
||||||
|
expected/actual. Only one of these loops get entered. */ |
||||||
|
for(; layer < actual.layerCount(); ++layer) { |
||||||
|
_state->layerOffsets[layer] = _state->attributes.size(); |
||||||
|
|
||||||
|
for(UnsignedInt inActual = 0, inActualMax = actual.attributeCount(layer); inActual != inActualMax; ++inActual) |
||||||
|
arrayAppend(_state->attributes, InPlaceInit, AttributeState::OnlyInActual, inActual, ~UnsignedInt{}); |
||||||
|
|
||||||
|
_state->materialState = Utility::max(_state->materialState, MaterialState::DifferentLayers); |
||||||
|
} |
||||||
|
for(; layer < expected.layerCount(); ++layer) { |
||||||
|
_state->layerOffsets[layer] = _state->attributes.size(); |
||||||
|
|
||||||
|
for(UnsignedInt inExpected = 0, inExpectedMax = expected.attributeCount(layer); inExpected != inExpectedMax; ++inExpected) |
||||||
|
arrayAppend(_state->attributes, InPlaceInit, AttributeState::OnlyInExpected, ~UnsignedInt{}, inExpected); |
||||||
|
|
||||||
|
_state->materialState = Utility::max(_state->materialState, MaterialState::DifferentLayers); |
||||||
|
} |
||||||
|
|
||||||
|
CORRADE_INTERNAL_ASSERT(layer == _state->layerOffsets.size() - 1); |
||||||
|
_state->layerOffsets[layer] = _state->attributes.size(); |
||||||
|
|
||||||
|
/** @todo If there's a large sequence of Same attributes, elide the middle
|
||||||
|
(mark it with SameEllipsis, e.g., and leave at most 3 before and 3 |
||||||
|
after each difference), and skip them when printing unless Verbose is |
||||||
|
set. Would become practically useful only once there's really a lot |
||||||
|
material attributes in a single layer, currently not really. */ |
||||||
|
|
||||||
|
return _state->materialState == MaterialState::Same ? TestSuite::ComparisonStatusFlags{} : TestSuite::ComparisonStatusFlag::Failed; |
||||||
|
} |
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
void printAttribute(Debug& out, const Trade::MaterialAttributeData& attribute, const AttributeState state, const bool isActual) { |
||||||
|
out << Debug::newline << " "; |
||||||
|
if(state == AttributeState::Same) |
||||||
|
out << " "; |
||||||
|
else if(isActual) |
||||||
|
out << Debug::color(Debug::Color::Green) << "+"; |
||||||
|
else |
||||||
|
out << Debug::color(Debug::Color::Red) << "-"; |
||||||
|
if(state == AttributeState::DifferentType || |
||||||
|
state == AttributeState::DifferentValue) |
||||||
|
out << Debug::resetColor; |
||||||
|
|
||||||
|
out << "" << attribute.name() << "@"; |
||||||
|
|
||||||
|
if(state == AttributeState::DifferentType) |
||||||
|
out << Debug::color(isActual ? Debug::Color::Green : Debug::Color::Red); |
||||||
|
out << Debug::packed << attribute.type(); |
||||||
|
if(state == AttributeState::DifferentType) |
||||||
|
out << Debug::resetColor; |
||||||
|
out << Debug::nospace << ":"; |
||||||
|
|
||||||
|
if(state == AttributeState::DifferentType || |
||||||
|
state == AttributeState::DifferentValue) |
||||||
|
out << Debug::color(isActual ? Debug::Color::Green : Debug::Color::Red); |
||||||
|
#ifdef CORRADE_TARGET_GCC |
||||||
|
#pragma GCC diagnostic push |
||||||
|
#pragma GCC diagnostic error "-Wswitch" |
||||||
|
#endif |
||||||
|
switch(attribute.type()) { |
||||||
|
#define _c(type) case Trade::MaterialAttributeType::type: \ |
||||||
|
out << Debug::packed << attribute.value<type>(); \
|
||||||
|
break; |
||||||
|
#define _ct(name, type) case Trade::MaterialAttributeType::name: \ |
||||||
|
out << Debug::packed << attribute.value<type>(); \
|
||||||
|
break; |
||||||
|
_ct(Bool, bool) |
||||||
|
/* LCOV_EXCL_START */ |
||||||
|
_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) |
||||||
|
/* LCOV_EXCL_STOP */ |
||||||
|
_ct(Pointer, const void*) |
||||||
|
_ct(MutablePointer, void*) |
||||||
|
_ct(String, Containers::StringView) |
||||||
|
_ct(TextureSwizzle, Trade::MaterialTextureSwizzle) |
||||||
|
#undef _c |
||||||
|
#undef _ct |
||||||
|
case Trade::MaterialAttributeType::Buffer: |
||||||
|
out << Containers::arrayCast<const char>(attribute.value<Containers::ArrayView<const void>>()); |
||||||
|
} |
||||||
|
#ifdef CORRADE_TARGET_GCC |
||||||
|
#pragma GCC diagnostic pop |
||||||
|
#endif |
||||||
|
|
||||||
|
if(state != AttributeState::Same) |
||||||
|
out << Debug::resetColor; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
void Comparator<DebugTools::CompareMaterial>::printMessage(const TestSuite::ComparisonStatusFlags, Debug& out, const Containers::StringView actual, const Containers::StringView expected) const { |
||||||
|
out << "Materials" << actual << "and" << expected; |
||||||
|
|
||||||
|
if(_state->materialState == MaterialState::DifferentLayers) { |
||||||
|
out << "have different layers."; |
||||||
|
} else if(_state->materialState == MaterialState::DifferentAttributes) { |
||||||
|
out << "have different attributes."; |
||||||
|
} else if(_state->materialState == MaterialState::DifferentAttributeTypes) { |
||||||
|
out << "have different attribute types."; |
||||||
|
} else if(_state->materialState == MaterialState::DifferentAttributeValues) { |
||||||
|
out << "have different attribute values."; |
||||||
|
} else if(_state->materialState == MaterialState::DifferentTypes) { |
||||||
|
out << "have different types."; |
||||||
|
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ |
||||||
|
|
||||||
|
out << Debug::color(Debug::Color::Green) << "Actual (+)" |
||||||
|
<< Debug::resetColor << "vs" << Debug::color(Debug::Color::Red) |
||||||
|
<< "expected (-)" << Debug::resetColor << Debug::nospace << ":"; |
||||||
|
|
||||||
|
/* Print the type, or both if they differ */ |
||||||
|
/** @todo Or maybe if it's MaterialState::DifferentType print just this and
|
||||||
|
skip the attributes? Because everything else that's printed is the |
||||||
|
same... */ |
||||||
|
if(_state->expected->types()) { |
||||||
|
out << Debug::newline << " "; |
||||||
|
if(_state->expected->types() != _state->actual->types()) |
||||||
|
out << Debug::color(Debug::Color::Red) << "-" << Debug::nospace; |
||||||
|
else |
||||||
|
out << ""; |
||||||
|
if(_state->actual->types() && _state->expected->types() != _state->actual->types()) |
||||||
|
out << Debug::resetColor; |
||||||
|
out << "Types:"; |
||||||
|
if(_state->actual->types() && _state->expected->types() != _state->actual->types()) |
||||||
|
out << Debug::color(Debug::Color::Red); |
||||||
|
out << Debug::packed << _state->expected->types() << Debug::resetColor; |
||||||
|
} |
||||||
|
if(_state->actual->types() && _state->actual->types() != _state->expected->types()) { |
||||||
|
out << Debug::newline << " " << Debug::color(Debug::Color::Green) << "+" << Debug::nospace; |
||||||
|
if(_state->expected->types()) out << Debug::resetColor; |
||||||
|
out << "Types:"; |
||||||
|
if(_state->expected->types()) out << Debug::color(Debug::Color::Green); |
||||||
|
out << Debug::packed << _state->actual->types() << Debug::resetColor; |
||||||
|
} |
||||||
|
|
||||||
|
/* Print content of both materials, interleaved, with layers and attributes
|
||||||
|
that differ marked with +/- */ |
||||||
|
for(UnsignedInt layer = 0, layerMax = _state->layerOffsets.size() - 1; layer != layerMax; ++layer) { |
||||||
|
/* Show layer header only if there's more than one and the base
|
||||||
|
layer isn't empty */ |
||||||
|
if(_state->layerOffsets.size() != 2 || _state->layerOffsets[1] != 0) { |
||||||
|
out << Debug::newline << " "; |
||||||
|
if(layer >= _state->actual->layerCount()) |
||||||
|
out << Debug::color(Debug::Color::Red) << "-" << Debug::nospace; |
||||||
|
else if(layer >= _state->expected->layerCount()) |
||||||
|
out << Debug::color(Debug::Color::Green) << "+" << Debug::nospace; |
||||||
|
else |
||||||
|
out << ""; |
||||||
|
if(layer == 0) |
||||||
|
out << "Base layer:"; |
||||||
|
else |
||||||
|
out << "Layer" << layer << Debug::nospace << ":"; |
||||||
|
if(layer >= _state->actual->layerCount() || layer >= _state->expected->layerCount()) |
||||||
|
out << Debug::resetColor; |
||||||
|
} |
||||||
|
|
||||||
|
/* Print attribute values indented only if there's more than one
|
||||||
|
layer */ |
||||||
|
for(UnsignedInt id = _state->layerOffsets[layer], idMax = _state->layerOffsets[layer + 1]; id != idMax; ++id) { |
||||||
|
const Containers::Triple<AttributeState, UnsignedInt, UnsignedInt> attribute = _state->attributes[id]; |
||||||
|
const AttributeState state =attribute.first(); |
||||||
|
if(state != AttributeState::OnlyInActual) |
||||||
|
printAttribute(out, _state->expected->attributeData(layer, attribute.third()), state, false); |
||||||
|
if(state != AttributeState::Same && state != AttributeState::OnlyInExpected) { |
||||||
|
printAttribute(out, _state->actual->attributeData(layer, attribute.second()), state, true); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
}} |
||||||
@ -0,0 +1,109 @@ |
|||||||
|
#ifndef Magnum_DebugTools_CompareMaterial_h |
||||||
|
#define Magnum_DebugTools_CompareMaterial_h |
||||||
|
/*
|
||||||
|
This file is part of Magnum. |
||||||
|
|
||||||
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
||||||
|
2020, 2021, 2022 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::DebugTools::CompareMaterial |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <Corrade/Containers/Pointer.h> |
||||||
|
#include <Corrade/TestSuite/TestSuite.h> |
||||||
|
|
||||||
|
#include "Magnum/Magnum.h" |
||||||
|
#include "Magnum/DebugTools/visibility.h" |
||||||
|
#include "Magnum/Trade/Trade.h" |
||||||
|
|
||||||
|
namespace Magnum { namespace DebugTools { |
||||||
|
|
||||||
|
class CompareMaterial; |
||||||
|
|
||||||
|
}} |
||||||
|
|
||||||
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||||
|
/* If Doxygen sees this, all @ref Corrade::TestSuite links break (prolly
|
||||||
|
because the namespace is undocumented in this project) */ |
||||||
|
namespace Corrade { namespace TestSuite { |
||||||
|
|
||||||
|
template<> class MAGNUM_DEBUGTOOLS_EXPORT Comparator<Magnum::DebugTools::CompareMaterial> { |
||||||
|
public: |
||||||
|
explicit Comparator(); |
||||||
|
~Comparator(); |
||||||
|
|
||||||
|
ComparisonStatusFlags operator()(const Magnum::Trade::MaterialData& actual, const Magnum::Trade::MaterialData& expected); |
||||||
|
|
||||||
|
void printMessage(ComparisonStatusFlags flags, Utility::Debug& out, Containers::StringView actual, Containers::StringView expected) const; |
||||||
|
|
||||||
|
private: |
||||||
|
struct State; |
||||||
|
Containers::Pointer<State> _state; |
||||||
|
}; |
||||||
|
|
||||||
|
}} |
||||||
|
#endif |
||||||
|
|
||||||
|
namespace Magnum { namespace DebugTools { |
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Material comparator for @ref Corrade::TestSuite |
||||||
|
@m_since_latest |
||||||
|
|
||||||
|
Compares @ref Trade::MaterialData instances, printing the differences in the |
||||||
|
two if they have a different type, different layer count, different attributes, |
||||||
|
and different type or different value of the same attribute. Pass the |
||||||
|
comparator to @ref CORRADE_COMPARE_AS() along with an actual and expected |
||||||
|
material: |
||||||
|
|
||||||
|
@snippet debugtools-comparematerial.cpp usage |
||||||
|
|
||||||
|
Based on actual materials used, in case of a comparison failure the comparator |
||||||
|
can give for example the following output: |
||||||
|
|
||||||
|
@m_class{m-console-wrap} |
||||||
|
|
||||||
|
@include debugtools-comparematerial.ansi |
||||||
|
|
||||||
|
All @ref Trade::MaterialAttributeType are supported. |
||||||
|
|
||||||
|
@see @ref CompareImage |
||||||
|
*/ |
||||||
|
class MAGNUM_DEBUGTOOLS_EXPORT CompareMaterial { |
||||||
|
public: |
||||||
|
explicit CompareMaterial(); |
||||||
|
|
||||||
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||||
|
TestSuite::Comparator<CompareMaterial>& comparator() { |
||||||
|
return _c; |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
private: |
||||||
|
TestSuite::Comparator<CompareMaterial> _c; |
||||||
|
}; |
||||||
|
|
||||||
|
}} |
||||||
|
|
||||||
|
#endif |
||||||
@ -0,0 +1,323 @@ |
|||||||
|
/*
|
||||||
|
This file is part of Magnum. |
||||||
|
|
||||||
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
||||||
|
2020, 2021, 2022 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <sstream> |
||||||
|
#include <Corrade/Containers/ArrayView.h> |
||||||
|
#include <Corrade/TestSuite/Tester.h> |
||||||
|
#include <Corrade/Utility/DebugStl.h> |
||||||
|
|
||||||
|
#include "Magnum/DebugTools/CompareMaterial.h" |
||||||
|
#include "Magnum/Math/Color.h" |
||||||
|
#include "Magnum/Trade/MaterialData.h" |
||||||
|
|
||||||
|
namespace Magnum { namespace DebugTools { namespace Test { namespace { |
||||||
|
|
||||||
|
struct CompareMaterialTest: TestSuite::Tester { |
||||||
|
explicit CompareMaterialTest(); |
||||||
|
|
||||||
|
void same(); |
||||||
|
void different(); |
||||||
|
void differentReverse(); |
||||||
|
}; |
||||||
|
|
||||||
|
using namespace Containers::Literals; |
||||||
|
using namespace Math::Literals; |
||||||
|
|
||||||
|
const struct { |
||||||
|
const char* name; |
||||||
|
Trade::MaterialData material; |
||||||
|
} SameData[]{ |
||||||
|
{"empty", Trade::MaterialData{{}, {}}}, |
||||||
|
{"empty with types", Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness|Trade::MaterialType::PbrClearCoat, {}}}, |
||||||
|
{"base attributes", Trade::MaterialData{Trade::MaterialType::Phong, { |
||||||
|
{Trade::MaterialAttribute::DiffuseColor, 0x556699aa_rgbaf}, |
||||||
|
{Trade::MaterialAttribute::NormalTexture, 5u}, |
||||||
|
{"name", "hello"_s}, |
||||||
|
}}}, |
||||||
|
{"layers", Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness|Trade::MaterialType::PbrClearCoat, { |
||||||
|
{Trade::MaterialAttribute::NormalTexture, 5u}, |
||||||
|
{Trade::MaterialLayer::ClearCoat}, |
||||||
|
{Trade::MaterialAttribute::LayerFactor, 0.76f}, |
||||||
|
{"name", "hello"_s}, |
||||||
|
}, {1, 3, 4}}}, |
||||||
|
}; |
||||||
|
|
||||||
|
const struct { |
||||||
|
const char* name; |
||||||
|
Trade::MaterialData actual; |
||||||
|
Trade::MaterialData expected; |
||||||
|
const char* message; |
||||||
|
const char* messageReverse; |
||||||
|
} DifferentData[]{ |
||||||
|
{"empty, different types", |
||||||
|
Trade::MaterialData{Trade::MaterialType::Flat, {}}, |
||||||
|
Trade::MaterialData{Trade::MaterialType::PbrClearCoat|Trade::MaterialType::PbrMetallicRoughness, {}}, |
||||||
|
"Materials a and b have different types. Actual (+) vs expected (-):\n" |
||||||
|
" -Types: PbrMetallicRoughness|PbrClearCoat\n" |
||||||
|
" +Types: Flat\n", |
||||||
|
"Materials b and a have different types. Actual (+) vs expected (-):\n" |
||||||
|
" -Types: Flat\n" |
||||||
|
" +Types: PbrMetallicRoughness|PbrClearCoat\n"}, |
||||||
|
{"different types", |
||||||
|
Trade::MaterialData{Trade::MaterialType::Flat, { |
||||||
|
{Trade::MaterialAttribute::BaseColor, 0xff00ffff_rgbaf}, |
||||||
|
}}, |
||||||
|
Trade::MaterialData{Trade::MaterialType::PbrClearCoat|Trade::MaterialType::PbrMetallicRoughness, { |
||||||
|
{Trade::MaterialAttribute::BaseColor, 0xff00ffff_rgbaf}, |
||||||
|
}}, |
||||||
|
"Materials a and b have different types. Actual (+) vs expected (-):\n" |
||||||
|
" -Types: PbrMetallicRoughness|PbrClearCoat\n" |
||||||
|
" +Types: Flat\n" |
||||||
|
" Base layer:\n" |
||||||
|
" BaseColor @ Vector4: {1, 0, 1, 1}\n", |
||||||
|
"Materials b and a have different types. Actual (+) vs expected (-):\n" |
||||||
|
" -Types: Flat\n" |
||||||
|
" +Types: PbrMetallicRoughness|PbrClearCoat\n" |
||||||
|
" Base layer:\n" |
||||||
|
" BaseColor @ Vector4: {1, 0, 1, 1}\n"}, |
||||||
|
{"different types, one empty", |
||||||
|
Trade::MaterialData{Trade::MaterialType::Flat, { |
||||||
|
{Trade::MaterialAttribute::BaseColor, 0xff00ffff_rgbaf} |
||||||
|
}}, |
||||||
|
Trade::MaterialData{{}, { |
||||||
|
{Trade::MaterialAttribute::BaseColor, 0xff00ffff_rgbaf} |
||||||
|
}}, |
||||||
|
"Materials a and b have different types. Actual (+) vs expected (-):\n" |
||||||
|
" +Types: Flat\n" |
||||||
|
" Base layer:\n" |
||||||
|
" BaseColor @ Vector4: {1, 0, 1, 1}\n", |
||||||
|
"Materials b and a have different types. Actual (+) vs expected (-):\n" |
||||||
|
" -Types: Flat\n" |
||||||
|
" Base layer:\n" |
||||||
|
" BaseColor @ Vector4: {1, 0, 1, 1}\n"}, |
||||||
|
{"different attributes", |
||||||
|
Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness, { |
||||||
|
{Trade::MaterialAttribute::DoubleSided, true}, |
||||||
|
{Trade::MaterialAttribute::NormalTexture, 5u}, |
||||||
|
{Trade::MaterialAttribute::NormalTextureScale, 0.5f}, |
||||||
|
{Trade::MaterialAttribute::OcclusionTexture, 3u}, |
||||||
|
}}, |
||||||
|
Trade::MaterialData{Trade::MaterialType::PbrMetallicRoughness, { |
||||||
|
{Trade::MaterialAttribute::Metalness, 5.5f}, |
||||||
|
{Trade::MaterialAttribute::NormalTexture, 5u}, |
||||||
|
{Trade::MaterialAttribute::NormalTextureLayer, 2u}, |
||||||
|
}}, |
||||||
|
"Materials a and b have different attributes. Actual (+) vs expected (-):\n" |
||||||
|
" Types: PbrMetallicRoughness\n" |
||||||
|
" Base layer:\n" |
||||||
|
" + DoubleSided @ Bool: true\n" |
||||||
|
" - Metalness @ Float: 5.5\n" |
||||||
|
" NormalTexture @ UnsignedInt: 5\n" |
||||||
|
" - NormalTextureLayer @ UnsignedInt: 2\n" |
||||||
|
" + NormalTextureScale @ Float: 0.5\n" |
||||||
|
" + OcclusionTexture @ UnsignedInt: 3\n", |
||||||
|
"Materials b and a have different attributes. Actual (+) vs expected (-):\n" |
||||||
|
" Types: PbrMetallicRoughness\n" |
||||||
|
" Base layer:\n" |
||||||
|
" - DoubleSided @ Bool: true\n" |
||||||
|
" + Metalness @ Float: 5.5\n" |
||||||
|
" NormalTexture @ UnsignedInt: 5\n" |
||||||
|
" + NormalTextureLayer @ UnsignedInt: 2\n" |
||||||
|
" - NormalTextureScale @ Float: 0.5\n" |
||||||
|
" - OcclusionTexture @ UnsignedInt: 3\n"}, |
||||||
|
{"different attribute types", |
||||||
|
Trade::MaterialData{{}, { |
||||||
|
{"pointer", reinterpret_cast<void*>(0xdead)}, |
||||||
|
{"integer", 5u}, |
||||||
|
{"scale", 0.5f}, |
||||||
|
}}, |
||||||
|
Trade::MaterialData{{}, { |
||||||
|
{"pointer", reinterpret_cast<const void*>(0xdead)}, |
||||||
|
{"integer", 5}, |
||||||
|
{"scale", "small"}, |
||||||
|
}}, |
||||||
|
"Materials a and b have different attribute types. Actual (+) vs expected (-):\n" |
||||||
|
" Base layer:\n" |
||||||
|
" - integer @ Int: 5\n" |
||||||
|
" + integer @ UnsignedInt: 5\n" |
||||||
|
" - pointer @ Pointer: 0xdead\n" |
||||||
|
" + pointer @ MutablePointer: 0xdead\n" |
||||||
|
" - scale @ String: small\n" |
||||||
|
" + scale @ Float: 0.5\n", |
||||||
|
"Materials b and a have different attribute types. Actual (+) vs expected (-):\n" |
||||||
|
" Base layer:\n" |
||||||
|
" - integer @ UnsignedInt: 5\n" |
||||||
|
" + integer @ Int: 5\n" |
||||||
|
" - pointer @ MutablePointer: 0xdead\n" |
||||||
|
" + pointer @ Pointer: 0xdead\n" |
||||||
|
" - scale @ Float: 0.5\n" |
||||||
|
" + scale @ String: small\n"}, |
||||||
|
{"different attribute values", |
||||||
|
Trade::MaterialData{{}, { |
||||||
|
{Trade::MaterialAttribute::Metalness, 0.3f}, |
||||||
|
{Trade::MaterialAttribute::NormalTexture, 5u}, |
||||||
|
{Trade::MaterialAttribute::NormalTextureSwizzle, Trade::MaterialTextureSwizzle::RGB}, |
||||||
|
{"buffer", Containers::ArrayView<const void>{"\x56\x78\x22"}}, |
||||||
|
{"pointer", reinterpret_cast<const void*>(0xbeef)}, |
||||||
|
{"pointerMutable", reinterpret_cast<void*>(0xdead)}, |
||||||
|
}}, |
||||||
|
Trade::MaterialData{{}, { |
||||||
|
{Trade::MaterialAttribute::Metalness, 5.5f}, |
||||||
|
{Trade::MaterialAttribute::NormalTexture, 5u}, |
||||||
|
{Trade::MaterialAttribute::NormalTextureSwizzle, Trade::MaterialTextureSwizzle::RG}, |
||||||
|
{"buffer", Containers::ArrayView<const void>{"\x56\x78\x22"}}, |
||||||
|
{"pointer", reinterpret_cast<const void*>(0xbeef)}, |
||||||
|
{"pointerMutable", reinterpret_cast<void*>(0xdead)}, |
||||||
|
}}, |
||||||
|
"Materials a and b have different attribute values. Actual (+) vs expected (-):\n" |
||||||
|
" Base layer:\n" |
||||||
|
" - Metalness @ Float: 5.5\n" |
||||||
|
" + Metalness @ Float: 0.3\n" |
||||||
|
" NormalTexture @ UnsignedInt: 5\n" |
||||||
|
" - NormalTextureSwizzle @ TextureSwizzle: RG\n" |
||||||
|
" + NormalTextureSwizzle @ TextureSwizzle: RGB\n" |
||||||
|
" buffer @ Buffer: {86, 120, 34, 0}\n" |
||||||
|
" pointer @ Pointer: 0xbeef\n" |
||||||
|
" pointerMutable @ MutablePointer: 0xdead\n", |
||||||
|
"Materials b and a have different attribute values. Actual (+) vs expected (-):\n" |
||||||
|
" Base layer:\n" |
||||||
|
" - Metalness @ Float: 0.3\n" |
||||||
|
" + Metalness @ Float: 5.5\n" |
||||||
|
" NormalTexture @ UnsignedInt: 5\n" |
||||||
|
" - NormalTextureSwizzle @ TextureSwizzle: RGB\n" |
||||||
|
" + NormalTextureSwizzle @ TextureSwizzle: RG\n" |
||||||
|
" buffer @ Buffer: {86, 120, 34, 0}\n" |
||||||
|
" pointer @ Pointer: 0xbeef\n" |
||||||
|
" pointerMutable @ MutablePointer: 0xdead\n"}, |
||||||
|
{"different attributes in layers", |
||||||
|
Trade::MaterialData{{}, { |
||||||
|
{Trade::MaterialAttribute::DoubleSided, true}, |
||||||
|
{Trade::MaterialAttribute::NormalTexture, 5u}, |
||||||
|
{Trade::MaterialAttribute::NormalTextureScale, 0.5f}, |
||||||
|
{Trade::MaterialAttribute::OcclusionTexture, 3u}, |
||||||
|
{"texturePointer", reinterpret_cast<void*>(0xdead)}, |
||||||
|
}, {3, 5}}, |
||||||
|
Trade::MaterialData{{}, { |
||||||
|
{Trade::MaterialAttribute::DoubleSided, false}, |
||||||
|
{Trade::MaterialAttribute::NormalTexture, 5u}, |
||||||
|
{Trade::MaterialAttribute::OcclusionTexture, 3u}, |
||||||
|
{"texturePointer", reinterpret_cast<const void*>(0xdead)}, |
||||||
|
{Trade::MaterialAttribute::NormalTextureLayer, 2u}, |
||||||
|
}, {2, 4, 5}}, |
||||||
|
"Materials a and b have different layers. Actual (+) vs expected (-):\n" |
||||||
|
" Base layer:\n" |
||||||
|
" - DoubleSided @ Bool: false\n" |
||||||
|
" + DoubleSided @ Bool: true\n" |
||||||
|
" NormalTexture @ UnsignedInt: 5\n" |
||||||
|
" + NormalTextureScale @ Float: 0.5\n" |
||||||
|
" Layer 1:\n" |
||||||
|
" OcclusionTexture @ UnsignedInt: 3\n" |
||||||
|
" - texturePointer @ Pointer: 0xdead\n" |
||||||
|
" + texturePointer @ MutablePointer: 0xdead\n" |
||||||
|
" -Layer 2:\n" |
||||||
|
" - NormalTextureLayer @ UnsignedInt: 2\n", |
||||||
|
"Materials b and a have different layers. Actual (+) vs expected (-):\n" |
||||||
|
" Base layer:\n" |
||||||
|
" - DoubleSided @ Bool: true\n" |
||||||
|
" + DoubleSided @ Bool: false\n" |
||||||
|
" NormalTexture @ UnsignedInt: 5\n" |
||||||
|
" - NormalTextureScale @ Float: 0.5\n" |
||||||
|
" Layer 1:\n" |
||||||
|
" OcclusionTexture @ UnsignedInt: 3\n" |
||||||
|
" - texturePointer @ MutablePointer: 0xdead\n" |
||||||
|
" + texturePointer @ Pointer: 0xdead\n" |
||||||
|
" +Layer 2:\n" |
||||||
|
" + NormalTextureLayer @ UnsignedInt: 2\n"}, |
||||||
|
{"different (empty) layer count", |
||||||
|
Trade::MaterialData{{}, {}}, |
||||||
|
Trade::MaterialData{{}, {}, {0, 0, 0}}, |
||||||
|
"Materials a and b have different layers. Actual (+) vs expected (-):\n" |
||||||
|
" Base layer:\n" |
||||||
|
" -Layer 1:\n" |
||||||
|
" -Layer 2:\n", |
||||||
|
"Materials b and a have different layers. Actual (+) vs expected (-):\n" |
||||||
|
" Base layer:\n" |
||||||
|
" +Layer 1:\n" |
||||||
|
" +Layer 2:\n"}, |
||||||
|
}; |
||||||
|
|
||||||
|
CompareMaterialTest::CompareMaterialTest() { |
||||||
|
addInstancedTests({&CompareMaterialTest::same}, |
||||||
|
Containers::arraySize(SameData)); |
||||||
|
|
||||||
|
addInstancedTests({&CompareMaterialTest::different, |
||||||
|
&CompareMaterialTest::differentReverse}, |
||||||
|
Containers::arraySize(DifferentData)); |
||||||
|
} |
||||||
|
|
||||||
|
void CompareMaterialTest::same() { |
||||||
|
auto&& data = SameData[testCaseInstanceId()]; |
||||||
|
setTestCaseDescription(data.name); |
||||||
|
|
||||||
|
CORRADE_COMPARE_AS(data.material, data.material, CompareMaterial); |
||||||
|
} |
||||||
|
|
||||||
|
void CompareMaterialTest::different() { |
||||||
|
auto&& data = DifferentData[testCaseInstanceId()]; |
||||||
|
setTestCaseDescription(data.name); |
||||||
|
|
||||||
|
TestSuite::Comparator<CompareMaterial> compare; |
||||||
|
TestSuite::ComparisonStatusFlags flags = compare(data.actual, data.expected); |
||||||
|
CORRADE_COMPARE(flags, TestSuite::ComparisonStatusFlag::Failed); |
||||||
|
|
||||||
|
CORRADE_INFO("Visual color verification:"); |
||||||
|
{ |
||||||
|
Debug out; |
||||||
|
compare.printMessage(flags, out, "a", "b"); |
||||||
|
} |
||||||
|
|
||||||
|
std::ostringstream out; |
||||||
|
{ |
||||||
|
Debug dc{&out, Debug::Flag::DisableColors}; |
||||||
|
compare.printMessage(flags, dc, "a", "b"); |
||||||
|
} |
||||||
|
CORRADE_COMPARE(out.str(), data.message); |
||||||
|
} |
||||||
|
|
||||||
|
void CompareMaterialTest::differentReverse() { |
||||||
|
auto&& data = DifferentData[testCaseInstanceId()]; |
||||||
|
setTestCaseDescription(data.name); |
||||||
|
|
||||||
|
TestSuite::Comparator<CompareMaterial> compare; |
||||||
|
TestSuite::ComparisonStatusFlags flags = compare(data.expected, data.actual); |
||||||
|
CORRADE_COMPARE(flags, TestSuite::ComparisonStatusFlag::Failed); |
||||||
|
|
||||||
|
CORRADE_INFO("Visual color verification:"); |
||||||
|
{ |
||||||
|
Debug out; |
||||||
|
compare.printMessage(flags, out, "b", "a"); |
||||||
|
} |
||||||
|
|
||||||
|
std::ostringstream out; |
||||||
|
{ |
||||||
|
Debug dc{&out, Debug::Flag::DisableColors}; |
||||||
|
compare.printMessage(flags, dc, "b", "a"); |
||||||
|
} |
||||||
|
CORRADE_COMPARE(out.str(), data.messageReverse); |
||||||
|
} |
||||||
|
|
||||||
|
}}}} |
||||||
|
|
||||||
|
CORRADE_TEST_MAIN(Magnum::DebugTools::Test::CompareMaterialTest) |
||||||
Loading…
Reference in new issue