mirror of https://github.com/mosra/magnum.git
7 changed files with 378 additions and 1 deletions
@ -0,0 +1,60 @@ |
|||||||
|
/*
|
||||||
|
This file is part of Magnum. |
||||||
|
|
||||||
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
||||||
|
2020 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 "SkinData.h" |
||||||
|
|
||||||
|
#include "Magnum/Math/Matrix3.h" |
||||||
|
#include "Magnum/Math/Matrix4.h" |
||||||
|
#include "Magnum/Trade/Data.h" |
||||||
|
|
||||||
|
namespace Magnum { namespace Trade { |
||||||
|
|
||||||
|
template<UnsignedInt dimensions> SkinData<dimensions>::SkinData(Containers::Array<UnsignedInt>&& jointData, Containers::Array<MatrixTypeFor<dimensions, Float>>&& inverseBindMatrixData, const void* const importerState) noexcept: _jointData{std::move(jointData)}, _inverseBindMatrixData{std::move(inverseBindMatrixData)}, _importerState{importerState} { |
||||||
|
CORRADE_ASSERT(_jointData.size() == _inverseBindMatrixData.size(), |
||||||
|
"Trade::SkinData: joint and inverse bind matrix arrays have different size, got" << _jointData.size() << "and" << _inverseBindMatrixData.size(), ); |
||||||
|
} |
||||||
|
|
||||||
|
template<UnsignedInt dimensions> SkinData<dimensions>::SkinData(const std::initializer_list<UnsignedInt> joints, const std::initializer_list<MatrixTypeFor<dimensions, Float>> inverseBindMatrices, const void* const importerState): SkinData{Containers::array(joints), Containers::array(inverseBindMatrices), importerState} {} |
||||||
|
|
||||||
|
template<UnsignedInt dimensions> SkinData<dimensions>::SkinData(DataFlags, const Containers::ArrayView<const UnsignedInt> jointData, DataFlags, const Containers::ArrayView<const MatrixTypeFor<dimensions, Float>> inverseBindMatrixData, const void* const importerState) noexcept: SkinData<dimensions>{Containers::Array<UnsignedInt>{const_cast<UnsignedInt*>(jointData.data()), jointData.size(), reinterpret_cast<void(*)(UnsignedInt*, std::size_t)>(Implementation::nonOwnedArrayDeleter)}, Containers::Array<MatrixTypeFor<dimensions, Float>>{const_cast<MatrixTypeFor<dimensions, Float>*>(inverseBindMatrixData.data()), inverseBindMatrixData.size(), reinterpret_cast<void(*)(MatrixTypeFor<dimensions, Float>*, std::size_t)>(Implementation::nonOwnedArrayDeleter)}, importerState} {} |
||||||
|
|
||||||
|
template<UnsignedInt dimensions> SkinData<dimensions>::SkinData(SkinData<dimensions>&&) noexcept = default; |
||||||
|
|
||||||
|
template<UnsignedInt dimensions> SkinData<dimensions>& SkinData<dimensions>::operator=(SkinData<dimensions>&&) noexcept = default; |
||||||
|
|
||||||
|
template<UnsignedInt dimensions> Containers::Array<UnsignedInt> SkinData<dimensions>::releaseJointData() { |
||||||
|
return std::move(_jointData); |
||||||
|
} |
||||||
|
|
||||||
|
template<UnsignedInt dimensions> Containers::Array<MatrixTypeFor<dimensions, Float>> SkinData<dimensions>::releaseInverseBindMatrixData() { |
||||||
|
return std::move(_inverseBindMatrixData); |
||||||
|
} |
||||||
|
|
||||||
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||||
|
template class MAGNUM_TRADE_EXPORT SkinData<2>; |
||||||
|
template class MAGNUM_TRADE_EXPORT SkinData<3>; |
||||||
|
#endif |
||||||
|
|
||||||
|
}} |
||||||
@ -0,0 +1,154 @@ |
|||||||
|
#ifndef Magnum_Trade_SkinData_h |
||||||
|
#define Magnum_Trade_SkinData_h |
||||||
|
/*
|
||||||
|
This file is part of Magnum. |
||||||
|
|
||||||
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
||||||
|
2020 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::SkinData |
||||||
|
* @m_since_latest |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <Corrade/Containers/Array.h> |
||||||
|
|
||||||
|
#include "Magnum/DimensionTraits.h" |
||||||
|
#include "Magnum/Trade/Trade.h" |
||||||
|
#include "Magnum/Trade/visibility.h" |
||||||
|
|
||||||
|
namespace Magnum { namespace Trade { |
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Skin data |
||||||
|
@m_since_latest |
||||||
|
|
||||||
|
@see @ref SkinData2D, @ref SkinData3D, @ref AbstractImporter::skin2D(), |
||||||
|
@ref AbstractImporter::skin3D() |
||||||
|
*/ |
||||||
|
template<UnsignedInt dimensions> class SkinData { |
||||||
|
public: |
||||||
|
/**
|
||||||
|
* @brief Constructor |
||||||
|
* @param jointData IDs of objects that act as joints |
||||||
|
* @param inverseBindMatrixData Inverse bind matrix for each joint |
||||||
|
* @param importerState Importer-specific state |
||||||
|
* |
||||||
|
* The @p jointData and @p inverseBindMatrixData arrays are expected to |
||||||
|
* have the same size. |
||||||
|
*/ |
||||||
|
explicit SkinData(Containers::Array<UnsignedInt>&& jointData, Containers::Array<MatrixTypeFor<dimensions, Float>>&& inverseBindMatrixData, const void* importerState = nullptr) noexcept; |
||||||
|
|
||||||
|
/** @overload */ |
||||||
|
explicit SkinData(std::initializer_list<UnsignedInt> joints, std::initializer_list<MatrixTypeFor<dimensions, Float>> inverseBindMatrices, const void* importerState = nullptr); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Construct a non-owned skin data |
||||||
|
* @param jointDataFlags Ignored. Used only for a safer distinction |
||||||
|
* from the owning constructor. |
||||||
|
* @param jointData IDs of objects that act as joints |
||||||
|
* @param inverseBindMatrixDataFlags Ignored. Used only for a safer |
||||||
|
* distinction from the owning constructor. |
||||||
|
* @param inverseBindMatrixData Inverse bind matrix for each joint |
||||||
|
* @param importerState Importer-specific state |
||||||
|
* |
||||||
|
* The @p jointData and @p inverseBindMatrixData arrays are expected to |
||||||
|
* have the same size. |
||||||
|
*/ |
||||||
|
explicit SkinData(DataFlags jointDataFlags, Containers::ArrayView<const UnsignedInt> jointData, DataFlags inverseBindMatrixDataFlags, Containers::ArrayView<const MatrixTypeFor<dimensions, Float>> inverseBindMatrixData, const void* importerState = nullptr) noexcept; |
||||||
|
|
||||||
|
/** @brief Copying is not allowed */ |
||||||
|
SkinData(const SkinData<dimensions>&) = delete; |
||||||
|
|
||||||
|
/** @brief Move constructor */ |
||||||
|
SkinData(SkinData<dimensions>&& other) noexcept; |
||||||
|
|
||||||
|
/** @brief Copying is not allowed */ |
||||||
|
SkinData<dimensions>& operator=(const SkinData<dimensions>&) = delete; |
||||||
|
|
||||||
|
/** @brief Move assignment */ |
||||||
|
SkinData<dimensions>& operator=(SkinData<dimensions>&& other) noexcept; |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Joint IDs |
||||||
|
* |
||||||
|
* IDs of objects that act as joints. |
||||||
|
* @see @ref AbstractImporter::object2D(), |
||||||
|
* @ref AbstractImporter::object3D(), @ref releaseJointData() |
||||||
|
*/ |
||||||
|
Containers::ArrayView<const UnsignedInt> joints() const { return _jointData; } |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Inverse bind matrices |
||||||
|
* |
||||||
|
* Transforms each joint to the initial state for skinning to be |
||||||
|
* applied. The returned array has the same size as @ref joints(). |
||||||
|
*/ |
||||||
|
Containers::ArrayView<const MatrixTypeFor<dimensions, Float>> inverseBindMatrices() const { return _inverseBindMatrixData; } |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release joint data storage |
||||||
|
* |
||||||
|
* Releases the ownership of the joint ID array. The material then |
||||||
|
* behaves like if it has no joints. |
||||||
|
* @see @ref joints() |
||||||
|
*/ |
||||||
|
Containers::Array<UnsignedInt> releaseJointData(); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release inverse bind matrix data storage |
||||||
|
* |
||||||
|
* Releases the ownership of the inverse bind matrix array. The |
||||||
|
* material then behaves like if it has no matrices. |
||||||
|
* @see @ref inverseBindMatrices() |
||||||
|
*/ |
||||||
|
Containers::Array<MatrixTypeFor<dimensions, Float>> releaseInverseBindMatrixData(); |
||||||
|
|
||||||
|
/** @brief Importer-specific state */ |
||||||
|
const void* importerState() const { return _importerState; } |
||||||
|
|
||||||
|
private: |
||||||
|
/** @todo skeleton object ID? gltf has that but the use is unclear */ |
||||||
|
Containers::Array<UnsignedInt> _jointData; |
||||||
|
Containers::Array<MatrixTypeFor<dimensions, Float>> _inverseBindMatrixData; |
||||||
|
const void* _importerState; |
||||||
|
}; |
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Two-dimensional skin data |
||||||
|
@m_since_latest |
||||||
|
|
||||||
|
@see @ref AbstractImporter::skin2D() |
||||||
|
*/ |
||||||
|
typedef SkinData<2> SkinData2D; |
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Three-dimensional skin data |
||||||
|
@m_since_latest |
||||||
|
|
||||||
|
@see @ref AbstractImporter::skin3D() |
||||||
|
*/ |
||||||
|
typedef SkinData<3> SkinData3D; |
||||||
|
|
||||||
|
}} |
||||||
|
|
||||||
|
#endif |
||||||
@ -0,0 +1,155 @@ |
|||||||
|
/*
|
||||||
|
This file is part of Magnum. |
||||||
|
|
||||||
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
||||||
|
2020 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/TestSuite/Tester.h> |
||||||
|
#include <Corrade/Utility/DebugStl.h> |
||||||
|
|
||||||
|
#include "Magnum/Math/Matrix3.h" |
||||||
|
#include "Magnum/Math/Matrix4.h" |
||||||
|
#include "Magnum/Trade/SkinData.h" |
||||||
|
|
||||||
|
namespace Magnum { namespace Trade { namespace Test { namespace { |
||||||
|
|
||||||
|
struct SkinDataTest: TestSuite::Tester { |
||||||
|
explicit SkinDataTest(); |
||||||
|
|
||||||
|
void construct(); |
||||||
|
void constructNonOwned(); |
||||||
|
void constructDifferentSize(); |
||||||
|
void constructCopy(); |
||||||
|
void constructMove(); |
||||||
|
|
||||||
|
void release(); |
||||||
|
}; |
||||||
|
|
||||||
|
SkinDataTest::SkinDataTest() { |
||||||
|
addTests({&SkinDataTest::construct, |
||||||
|
&SkinDataTest::constructNonOwned, |
||||||
|
&SkinDataTest::constructDifferentSize, |
||||||
|
&SkinDataTest::constructCopy, |
||||||
|
&SkinDataTest::constructMove, |
||||||
|
|
||||||
|
&SkinDataTest::release}); |
||||||
|
} |
||||||
|
|
||||||
|
void SkinDataTest::construct() { |
||||||
|
int state; |
||||||
|
SkinData3D data{{0, 2, 3}, { |
||||||
|
Matrix4::translation(Vector3::zAxis(0.0f)), |
||||||
|
Matrix4::translation(Vector3::zAxis(2.0f)), |
||||||
|
Matrix4::translation(Vector3::zAxis(4.0f)), |
||||||
|
}, &state}; |
||||||
|
|
||||||
|
CORRADE_COMPARE(data.joints()[1], 2); |
||||||
|
CORRADE_COMPARE(data.inverseBindMatrices()[1], Matrix4::translation(Vector3::zAxis(2.0f))); |
||||||
|
CORRADE_COMPARE(data.importerState(), &state); |
||||||
|
} |
||||||
|
|
||||||
|
void SkinDataTest::constructNonOwned() { |
||||||
|
int state; |
||||||
|
const UnsignedInt jointData[]{0, 2, 3}; |
||||||
|
const Matrix4 inverseBindMatrixData[]{ |
||||||
|
Matrix4::translation(Vector3::zAxis(0.0f)), |
||||||
|
Matrix4::translation(Vector3::zAxis(2.0f)), |
||||||
|
Matrix4::translation(Vector3::zAxis(4.0f)) |
||||||
|
}; |
||||||
|
SkinData3D data{{}, jointData, {}, inverseBindMatrixData, &state}; |
||||||
|
|
||||||
|
CORRADE_COMPARE(data.joints().size(), 3); |
||||||
|
CORRADE_COMPARE(data.joints().data(), jointData); |
||||||
|
CORRADE_COMPARE(data.inverseBindMatrices().size(), 3); |
||||||
|
CORRADE_COMPARE(data.inverseBindMatrices().data(), inverseBindMatrixData); |
||||||
|
CORRADE_COMPARE(data.importerState(), &state); |
||||||
|
} |
||||||
|
|
||||||
|
void SkinDataTest::constructDifferentSize() { |
||||||
|
#ifdef CORRADE_NO_ASSERT |
||||||
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
||||||
|
#endif |
||||||
|
|
||||||
|
std::ostringstream out; |
||||||
|
Error redirectError{&out}; |
||||||
|
SkinData3D data{{0, 2}, {{}, {}, {}}}; |
||||||
|
CORRADE_COMPARE(out.str(), "Trade::SkinData: joint and inverse bind matrix arrays have different size, got 2 and 3\n"); |
||||||
|
} |
||||||
|
|
||||||
|
void SkinDataTest::constructCopy() { |
||||||
|
CORRADE_VERIFY(!(std::is_constructible<SkinData3D, const SkinData3D&>{})); |
||||||
|
CORRADE_VERIFY(!(std::is_assignable<SkinData3D, const SkinData3D&>{})); |
||||||
|
} |
||||||
|
|
||||||
|
void SkinDataTest::constructMove() { |
||||||
|
int state; |
||||||
|
SkinData3D a{{0, 2, 3}, { |
||||||
|
Matrix4::translation(Vector3::zAxis(0.0f)), |
||||||
|
Matrix4::translation(Vector3::zAxis(2.0f)), |
||||||
|
Matrix4::translation(Vector3::zAxis(4.0f)), |
||||||
|
}, &state}; |
||||||
|
|
||||||
|
SkinData3D b = std::move(a); |
||||||
|
CORRADE_COMPARE(b.joints()[1], 2); |
||||||
|
CORRADE_COMPARE(b.inverseBindMatrices()[1], Matrix4::translation(Vector3::zAxis(2.0f))); |
||||||
|
CORRADE_COMPARE(b.importerState(), &state); |
||||||
|
|
||||||
|
SkinData3D c{{}, {}}; |
||||||
|
c = std::move(b); |
||||||
|
CORRADE_COMPARE(c.joints()[1], 2); |
||||||
|
CORRADE_COMPARE(c.inverseBindMatrices()[1], Matrix4::translation(Vector3::zAxis(2.0f))); |
||||||
|
CORRADE_COMPARE(c.importerState(), &state); |
||||||
|
|
||||||
|
CORRADE_VERIFY(std::is_nothrow_move_constructible<SkinData2D>::value); |
||||||
|
CORRADE_VERIFY(std::is_nothrow_move_assignable<SkinData2D>::value); |
||||||
|
} |
||||||
|
|
||||||
|
void SkinDataTest::release() { |
||||||
|
Containers::Array<UnsignedInt> joints{Containers::InPlaceInit, {0, 2, 3}}; |
||||||
|
Containers::Array<Matrix3> inverseBindMatrices{Containers::InPlaceInit, { |
||||||
|
Matrix3::translation(Vector2::yAxis(0.0f)), |
||||||
|
Matrix3::translation(Vector2::yAxis(2.0f)), |
||||||
|
Matrix3::translation(Vector2::yAxis(4.0f)) |
||||||
|
}}; |
||||||
|
|
||||||
|
const void* jointsPointer = joints; |
||||||
|
const void* inverseBindMatricesPointer = inverseBindMatrices; |
||||||
|
|
||||||
|
SkinData2D data{std::move(joints), std::move(inverseBindMatrices)}; |
||||||
|
|
||||||
|
Containers::Array<UnsignedInt> releasedJoints = data.releaseJointData(); |
||||||
|
CORRADE_COMPARE(data.joints().size(), 0); |
||||||
|
CORRADE_COMPARE(data.inverseBindMatrices().size(), 3); |
||||||
|
CORRADE_COMPARE(releasedJoints.size(), 3); |
||||||
|
CORRADE_COMPARE(releasedJoints, jointsPointer); |
||||||
|
|
||||||
|
Containers::Array<Matrix3> releasedInverseBindMatrices = data.releaseInverseBindMatrixData(); |
||||||
|
CORRADE_COMPARE(data.joints().size(), 0); |
||||||
|
CORRADE_COMPARE(data.inverseBindMatrices().size(), 0); |
||||||
|
CORRADE_COMPARE(releasedInverseBindMatrices.size(), 3); |
||||||
|
CORRADE_COMPARE(releasedInverseBindMatrices, inverseBindMatricesPointer); |
||||||
|
} |
||||||
|
|
||||||
|
}}}} |
||||||
|
|
||||||
|
CORRADE_TEST_MAIN(Magnum::Trade::Test::SkinDataTest) |
||||||
Loading…
Reference in new issue