Initial commit
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_CONTAINERS_DEQUE_H_
|
||||
#define OZZ_OZZ_BASE_CONTAINERS_DEQUE_H_
|
||||
|
||||
#include <deque>
|
||||
|
||||
#include "ozz/base/containers/std_allocator.h"
|
||||
|
||||
namespace ozz {
|
||||
// Redirects std::deque to ozz::deque in order to replace std default allocator
|
||||
// by ozz::StdAllocator.
|
||||
template <class _Ty, class _Allocator = ozz::StdAllocator<_Ty>>
|
||||
using deque = std::deque<_Ty, _Allocator>;
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_CONTAINERS_DEQUE_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,51 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_CONTAINERS_LIST_H_
|
||||
#define OZZ_OZZ_BASE_CONTAINERS_LIST_H_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
// Removes constant conditional expression warning.
|
||||
#pragma warning(disable : 4127)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <list>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include "ozz/base/containers/std_allocator.h"
|
||||
|
||||
namespace ozz {
|
||||
// Redirects std::list to ozz::list in order to replace std default allocator by
|
||||
// ozz::StdAllocator.
|
||||
template <class _Ty, class _Allocator = ozz::StdAllocator<_Ty>>
|
||||
using list = std::list<_Ty, _Allocator>;
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_CONTAINERS_LIST_H_
|
||||
@@ -0,0 +1,70 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_CONTAINERS_MAP_H_
|
||||
#define OZZ_OZZ_BASE_CONTAINERS_MAP_H_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4702) // warning C4702: unreachable code
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include "ozz/base/containers/std_allocator.h"
|
||||
|
||||
namespace ozz {
|
||||
// Redirects std::map to ozz::map in order to replace std default allocator by
|
||||
// ozz::StdAllocator.
|
||||
template <class _Key, class _Ty, class _Pred = std::less<_Key>,
|
||||
class _Allocator = ozz::StdAllocator<std::pair<const _Key, _Ty>>>
|
||||
using map = std::map<_Key, _Ty, _Pred, _Allocator>;
|
||||
|
||||
// Implements a string comparator that can be used by std algorithm like maps.
|
||||
struct str_less {
|
||||
bool operator()(const char* const& _left, const char* const& _right) const {
|
||||
return strcmp(_left, _right) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Specializes std::map to use c-string as a key.
|
||||
template <class _Ty, class _Allocator =
|
||||
ozz::StdAllocator<std::pair<const char* const, _Ty>>>
|
||||
using cstring_map = std::map<const char*, _Ty, str_less, _Allocator>;
|
||||
|
||||
// Redirects std::multimap to ozz::MultiMap in order to replace std default
|
||||
// allocator by ozz::StdAllocator.
|
||||
template <class _Key, class _Ty, class _Pred = std::less<_Key>,
|
||||
class _Allocator = ozz::StdAllocator<std::pair<const _Key, _Ty>>>
|
||||
using multimap = std::multimap<_Key, _Ty, _Pred, _Allocator>;
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_CONTAINERS_MAP_H_
|
||||
@@ -0,0 +1,47 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_CONTAINERS_QUEUE_H_
|
||||
#define OZZ_OZZ_BASE_CONTAINERS_QUEUE_H_
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include "deque.h"
|
||||
|
||||
namespace ozz {
|
||||
// Redirects std::queue to ozz::queue in order to replace std default allocator
|
||||
// by ozz::StdAllocator.
|
||||
template <class _Ty, class _Container = deque<_Ty>>
|
||||
using queue = std::queue<_Ty, _Container>;
|
||||
|
||||
// Redirects std::priority_queue to ozz::priority_queue in order to replace std
|
||||
// default allocator by ozz::StdAllocator.
|
||||
template <class _Ty, class _Container = deque<_Ty>,
|
||||
class _Pred = std::less<typename _Container::value_type>>
|
||||
using priority_queue = std::priority_queue<_Ty, _Container, _Pred>;
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_CONTAINERS_QUEUE_H_
|
||||
@@ -0,0 +1,48 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_CONTAINERS_SET_H_
|
||||
#define OZZ_OZZ_BASE_CONTAINERS_SET_H_
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "ozz/base/containers/std_allocator.h"
|
||||
|
||||
namespace ozz {
|
||||
// Redirects std::set to ozz::set in order to replace std default allocator by
|
||||
// ozz::StdAllocator.
|
||||
template <class _Key, class _Pred = std::less<_Key>,
|
||||
class _Allocator = ozz::StdAllocator<_Key>>
|
||||
using set = std::set<_Key, _Pred, _Allocator>;
|
||||
|
||||
// Redirects std::multiset to ozz::multiset in order to replace std default
|
||||
// allocator by ozz::StdAllocator.
|
||||
template <class _Key, class _Pred = std::less<_Key>,
|
||||
class _Allocator = ozz::StdAllocator<_Key>>
|
||||
using multiset = std::multiset<_Key, _Pred, _Allocator>;
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_CONTAINERS_SET_H_
|
||||
@@ -0,0 +1,41 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_CONTAINERS_STACK_H_
|
||||
#define OZZ_OZZ_BASE_CONTAINERS_STACK_H_
|
||||
|
||||
#include <stack>
|
||||
|
||||
#include "deque.h"
|
||||
|
||||
namespace ozz {
|
||||
// Redirects std::stack to ozz::stack in order to replace std default allocator
|
||||
// by ozz::StdAllocator.
|
||||
template <class _Ty, class _Container = typename ozz::deque<_Ty>>
|
||||
using stack = std::stack<_Ty, _Container>;
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_CONTAINERS_STACK_H_
|
||||
@@ -0,0 +1,105 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_CONTAINERS_STD_ALLOCATOR_H_
|
||||
#define OZZ_OZZ_BASE_CONTAINERS_STD_ALLOCATOR_H_
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "ozz/base/memory/allocator.h"
|
||||
|
||||
namespace ozz {
|
||||
// Define a STL allocator compliant allocator->
|
||||
template <typename _Ty>
|
||||
class StdAllocator {
|
||||
public:
|
||||
typedef _Ty value_type; // Element type.
|
||||
typedef value_type* pointer; // Pointer to element.
|
||||
typedef value_type& reference; // Reference to element.
|
||||
typedef const value_type* const_pointer; // Constant pointer to element.
|
||||
typedef const value_type& const_reference; // Constant reference to element.
|
||||
typedef size_t size_type; // Quantities of elements.
|
||||
typedef ptrdiff_t difference_type; // Difference between two pointers.
|
||||
|
||||
StdAllocator() noexcept {}
|
||||
StdAllocator(const StdAllocator&) noexcept {}
|
||||
|
||||
template <class _Other>
|
||||
StdAllocator<value_type>(const StdAllocator<_Other>&) noexcept {}
|
||||
|
||||
template <class _Other>
|
||||
struct rebind {
|
||||
typedef StdAllocator<_Other> other;
|
||||
};
|
||||
|
||||
pointer address(reference _ref) const noexcept { return &_ref; }
|
||||
const_pointer address(const_reference _ref) const noexcept { return &_ref; }
|
||||
|
||||
template <class _Other, class... _Args>
|
||||
void construct(_Other* _ptr, _Args&&... _args) {
|
||||
::new (static_cast<void*>(_ptr)) _Other(std::forward<_Args>(_args)...);
|
||||
}
|
||||
|
||||
template <class _Other>
|
||||
void destroy(_Other* _ptr) {
|
||||
(void)_ptr;
|
||||
_ptr->~_Other();
|
||||
}
|
||||
|
||||
// Allocates array of _Count elements.
|
||||
pointer allocate(size_t _count) noexcept {
|
||||
// Makes sure to a use c like allocator, to avoid duplicated constructor
|
||||
// calls.
|
||||
return reinterpret_cast<pointer>(memory::default_allocator()->Allocate(
|
||||
sizeof(value_type) * _count, alignof(value_type)));
|
||||
}
|
||||
|
||||
// Deallocates object at _Ptr, ignores size.
|
||||
void deallocate(pointer _ptr, size_type) noexcept {
|
||||
memory::default_allocator()->Deallocate(_ptr);
|
||||
}
|
||||
|
||||
size_type max_size() const noexcept {
|
||||
return (~size_type(0)) / sizeof(value_type);
|
||||
}
|
||||
};
|
||||
|
||||
// Tests for allocator equality (always true).
|
||||
template <class _Ty, class _Other>
|
||||
inline bool operator==(const StdAllocator<_Ty>&,
|
||||
const StdAllocator<_Other>&) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Tests for allocator inequality (always false).
|
||||
template <class _Ty, class _Other>
|
||||
inline bool operator!=(const StdAllocator<_Ty>&,
|
||||
const StdAllocator<_Other>&) noexcept {
|
||||
return false;
|
||||
}
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_CONTAINERS_STD_ALLOCATOR_H_
|
||||
@@ -0,0 +1,41 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_CONTAINERS_STRING_H_
|
||||
#define OZZ_OZZ_BASE_CONTAINERS_STRING_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ozz/base/containers/std_allocator.h"
|
||||
|
||||
namespace ozz {
|
||||
// Redirects std::basic_string to ozz::string in order to replace std default
|
||||
// allocator by ozz::StdAllocator.
|
||||
using string =
|
||||
std::basic_string<char, std::char_traits<char>, ozz::StdAllocator<char>>;
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_CONTAINERS_STRING_H_
|
||||
@@ -0,0 +1,49 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_CONTAINERS_STRING_ARCHIVE_H_
|
||||
#define OZZ_OZZ_BASE_CONTAINERS_STRING_ARCHIVE_H_
|
||||
|
||||
#include "ozz/base/containers/string.h"
|
||||
#include "ozz/base/io/archive_traits.h"
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace io {
|
||||
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(ozz::string)
|
||||
|
||||
template <>
|
||||
struct Extern<ozz::string> {
|
||||
static void Save(OArchive& _archive, const ozz::string* _values,
|
||||
size_t _count);
|
||||
static void Load(IArchive& _archive, ozz::string* _values, size_t _count,
|
||||
uint32_t _version);
|
||||
};
|
||||
} // namespace io
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_CONTAINERS_STRING_ARCHIVE_H_
|
||||
@@ -0,0 +1,62 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_CONTAINERS_UNORDERED_MAP_H_
|
||||
#define OZZ_OZZ_BASE_CONTAINERS_UNORDERED_MAP_H_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4702) // warning C4702: unreachable code
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include "ozz/base/containers/std_allocator.h"
|
||||
|
||||
namespace ozz {
|
||||
|
||||
// Redirects std::unordered_map to ozz::unordered_map in order to replace std
|
||||
// default allocator by ozz::StdAllocator.
|
||||
template <class _Key, class _Ty, class _Hash = std::hash<_Key>,
|
||||
class _KeyEqual = std::equal_to<_Key>,
|
||||
class _Allocator = ozz::StdAllocator<std::pair<const _Key, _Ty>>>
|
||||
using unordered_map =
|
||||
std::unordered_map<_Key, _Ty, _Hash, _KeyEqual, _Allocator>;
|
||||
|
||||
// Redirects std::unordered_multimap to ozz::UnorderedMultiMap in order to
|
||||
// replace std default allocator by ozz::StdAllocator.
|
||||
template <class _Key, class _Ty, class _Hash = std::hash<_Key>,
|
||||
class _KeyEqual = std::equal_to<_Key>,
|
||||
class _Allocator = ozz::StdAllocator<std::pair<const _Key, _Ty>>>
|
||||
using unordered_multimap =
|
||||
std::unordered_multimap<_Key, _Ty, _Hash, _KeyEqual, _Allocator>;
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_CONTAINERS_UNORDERED_MAP_H_
|
||||
@@ -0,0 +1,52 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_CONTAINERS_UNORDERED_SET_H_
|
||||
#define OZZ_OZZ_BASE_CONTAINERS_UNORDERED_SET_H_
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
#include "ozz/base/containers/std_allocator.h"
|
||||
|
||||
namespace ozz {
|
||||
// Redirects std::unordered_set to ozz::UnorderedSet in order to replace std
|
||||
// default allocator by ozz::StdAllocator.
|
||||
template <class _Key, class _Hash = std::hash<_Key>,
|
||||
class _KeyEqual = std::equal_to<_Key>,
|
||||
class _Allocator = ozz::StdAllocator<_Key> >
|
||||
using unordered_set =
|
||||
std::unordered_set<_Key, _Hash, _KeyEqual, _Allocator>;
|
||||
|
||||
// Redirects std::unordered_multiset to ozz::UnorderedMultiSet in order to
|
||||
// replace std default allocator by ozz::StdAllocator.
|
||||
template <class _Key, class _Hash = std::hash<_Key>,
|
||||
class _KeyEqual = std::equal_to<_Key>,
|
||||
class _Allocator = ozz::StdAllocator<_Key> >
|
||||
using unordered_multiset =
|
||||
std::unordered_multiset<_Key, _Hash, _KeyEqual, _Allocator>;
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_CONTAINERS_UNORDERED_SET_H_
|
||||
@@ -0,0 +1,74 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_CONTAINERS_VECTOR_H_
|
||||
#define OZZ_OZZ_BASE_CONTAINERS_VECTOR_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "ozz/base/containers/std_allocator.h"
|
||||
|
||||
namespace ozz {
|
||||
// Redirects std::vector to ozz::vector in order to replace std default
|
||||
// allocator by ozz::StdAllocator.
|
||||
template <class _Ty, class _Allocator = ozz::StdAllocator<_Ty>>
|
||||
using vector = std::vector<_Ty, _Allocator>;
|
||||
|
||||
// Extends std::vector with two functions that gives access to the begin and the
|
||||
// end of its array of elements.
|
||||
|
||||
// Returns the mutable begin of the array of elements, or nullptr if
|
||||
// vector's empty.
|
||||
template <class _Ty, class _Allocator>
|
||||
inline _Ty* array_begin(std::vector<_Ty, _Allocator>& _vector) {
|
||||
return _vector.data();
|
||||
}
|
||||
|
||||
// Returns the non-mutable begin of the array of elements, or nullptr if
|
||||
// vector's empty.
|
||||
template <class _Ty, class _Allocator>
|
||||
inline const _Ty* array_begin(const std::vector<_Ty, _Allocator>& _vector) {
|
||||
return _vector.data();
|
||||
}
|
||||
|
||||
// Returns the mutable end of the array of elements, or nullptr if
|
||||
// vector's empty. Array end is one element past the last element of the
|
||||
// array, it cannot be dereferenced.
|
||||
template <class _Ty, class _Allocator>
|
||||
inline _Ty* array_end(std::vector<_Ty, _Allocator>& _vector) {
|
||||
return _vector.data() + _vector.size();
|
||||
}
|
||||
|
||||
// Returns the non-mutable end of the array of elements, or nullptr if
|
||||
// vector's empty. Array end is one element past the last element of the
|
||||
// array, it cannot be dereferenced.
|
||||
template <class _Ty, class _Allocator>
|
||||
inline const _Ty* array_end(const std::vector<_Ty, _Allocator>& _vector) {
|
||||
return _vector.data() + _vector.size();
|
||||
}
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_CONTAINERS_VECTOR_H_
|
||||
@@ -0,0 +1,72 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_CONTAINERS_VECTOR_ARCHIVE_H_
|
||||
#define OZZ_OZZ_BASE_CONTAINERS_VECTOR_ARCHIVE_H_
|
||||
|
||||
#include "ozz/base/containers/vector.h"
|
||||
#include "ozz/base/io/archive.h"
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace io {
|
||||
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE_T2(class _Ty, class _Allocator,
|
||||
std::vector<_Ty, _Allocator>)
|
||||
|
||||
template <class _Ty, class _Allocator>
|
||||
struct Extern<std::vector<_Ty, _Allocator>> {
|
||||
inline static void Save(OArchive& _archive,
|
||||
const std::vector<_Ty, _Allocator>* _values,
|
||||
size_t _count) {
|
||||
for (size_t i = 0; i < _count; i++) {
|
||||
const std::vector<_Ty, _Allocator>& vector = _values[i];
|
||||
const uint32_t size = static_cast<uint32_t>(vector.size());
|
||||
_archive << size;
|
||||
if (size > 0) {
|
||||
_archive << ozz::io::MakeArray(&vector[0], size);
|
||||
}
|
||||
}
|
||||
}
|
||||
inline static void Load(IArchive& _archive,
|
||||
std::vector<_Ty, _Allocator>* _values, size_t _count,
|
||||
uint32_t _version) {
|
||||
(void)_version;
|
||||
for (size_t i = 0; i < _count; i++) {
|
||||
std::vector<_Ty, _Allocator>& vector = _values[i];
|
||||
uint32_t size;
|
||||
_archive >> size;
|
||||
vector.resize(size);
|
||||
if (size > 0) {
|
||||
_archive >> ozz::io::MakeArray(&vector[0], size);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace io
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_CONTAINERS_VECTOR_ARCHIVE_H_
|
||||
@@ -0,0 +1,157 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_ENDIANNESS_H_
|
||||
#define OZZ_OZZ_BASE_ENDIANNESS_H_
|
||||
|
||||
// Declares endianness modes and functions to swap data from a mode to another.
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
namespace ozz {
|
||||
|
||||
// Declares supported endianness.
|
||||
enum Endianness {
|
||||
kBigEndian,
|
||||
kLittleEndian,
|
||||
};
|
||||
|
||||
// Get the native endianness of the targeted processor.
|
||||
// This function does not rely on a pre-processor definition as no standard
|
||||
// definition exists. It is rather implemented as a portable runtime function.
|
||||
inline Endianness GetNativeEndianness() {
|
||||
const union {
|
||||
uint16_t s;
|
||||
uint8_t c[2];
|
||||
} u = {1}; // Initializes u.s -> then read u.c.
|
||||
return Endianness(u.c[0]);
|
||||
}
|
||||
|
||||
// Declare the endian swapper struct that is aimed to be specialized (template
|
||||
// meaning) for every type sizes.
|
||||
// The swapper provides two functions:
|
||||
// - void Swap(_Ty* _ty, size_t _count) swaps the array _ty of _count
|
||||
// elements in-place.
|
||||
// - _Ty Swap(_Ty _ty) returns a swapped copy of _ty.
|
||||
// It can be used directly if _Ty is known or through EndianSwap function.
|
||||
// The default value of template attribute _size enables automatic
|
||||
// specialization selection.
|
||||
template <typename _Ty, size_t _size = sizeof(_Ty)>
|
||||
struct EndianSwapper;
|
||||
|
||||
// Internal macro used to swap two bytes.
|
||||
#define OZZ_BYTE_SWAP(_a, _b) \
|
||||
do { \
|
||||
const char temp = _a; \
|
||||
_a = _b; \
|
||||
_b = temp; \
|
||||
} while (0)
|
||||
|
||||
// EndianSwapper specialization for 1 byte types.
|
||||
template <typename _Ty>
|
||||
struct EndianSwapper<_Ty, 1> {
|
||||
OZZ_INLINE static void Swap(_Ty* _ty, size_t _count) {
|
||||
(void)_ty;
|
||||
(void)_count;
|
||||
}
|
||||
OZZ_INLINE static _Ty Swap(_Ty _ty) { return _ty; }
|
||||
};
|
||||
|
||||
// EndianSwapper specialization for 2 bytes types.
|
||||
template <typename _Ty>
|
||||
struct EndianSwapper<_Ty, 2> {
|
||||
OZZ_INLINE static void Swap(_Ty* _ty, size_t _count) {
|
||||
char* alias = reinterpret_cast<char*>(_ty);
|
||||
for (size_t i = 0; i < _count * 2; i += 2) {
|
||||
OZZ_BYTE_SWAP(alias[i + 0], alias[i + 1]);
|
||||
}
|
||||
}
|
||||
OZZ_INLINE static _Ty Swap(_Ty _ty) { // Pass by copy to swap _ty in-place.
|
||||
char* alias = reinterpret_cast<char*>(&_ty);
|
||||
OZZ_BYTE_SWAP(alias[0], alias[1]);
|
||||
return _ty;
|
||||
}
|
||||
};
|
||||
|
||||
// EndianSwapper specialization for 4 bytes types.
|
||||
template <typename _Ty>
|
||||
struct EndianSwapper<_Ty, 4> {
|
||||
OZZ_INLINE static void Swap(_Ty* _ty, size_t _count) {
|
||||
char* alias = reinterpret_cast<char*>(_ty);
|
||||
for (size_t i = 0; i < _count * 4; i += 4) {
|
||||
OZZ_BYTE_SWAP(alias[i + 0], alias[i + 3]);
|
||||
OZZ_BYTE_SWAP(alias[i + 1], alias[i + 2]);
|
||||
}
|
||||
}
|
||||
OZZ_INLINE static _Ty Swap(_Ty _ty) { // Pass by copy to swap _ty in-place.
|
||||
char* alias = reinterpret_cast<char*>(&_ty);
|
||||
OZZ_BYTE_SWAP(alias[0], alias[3]);
|
||||
OZZ_BYTE_SWAP(alias[1], alias[2]);
|
||||
return _ty;
|
||||
}
|
||||
};
|
||||
|
||||
// EndianSwapper specialization for 8 bytes types.
|
||||
template <typename _Ty>
|
||||
struct EndianSwapper<_Ty, 8> {
|
||||
OZZ_INLINE static void Swap(_Ty* _ty, size_t _count) {
|
||||
char* alias = reinterpret_cast<char*>(_ty);
|
||||
for (size_t i = 0; i < _count * 8; i += 8) {
|
||||
OZZ_BYTE_SWAP(alias[i + 0], alias[i + 7]);
|
||||
OZZ_BYTE_SWAP(alias[i + 1], alias[i + 6]);
|
||||
OZZ_BYTE_SWAP(alias[i + 2], alias[i + 5]);
|
||||
OZZ_BYTE_SWAP(alias[i + 3], alias[i + 4]);
|
||||
}
|
||||
}
|
||||
OZZ_INLINE static _Ty Swap(_Ty _ty) { // Pass by copy to swap _ty in-place.
|
||||
char* alias = reinterpret_cast<char*>(&_ty);
|
||||
OZZ_BYTE_SWAP(alias[0], alias[7]);
|
||||
OZZ_BYTE_SWAP(alias[1], alias[6]);
|
||||
OZZ_BYTE_SWAP(alias[2], alias[5]);
|
||||
OZZ_BYTE_SWAP(alias[3], alias[4]);
|
||||
return _ty;
|
||||
}
|
||||
};
|
||||
|
||||
// OZZ_BYTE_SWAP is not useful anymore.
|
||||
#undef OZZ_BYTE_SWAP
|
||||
|
||||
// Helper function that swaps _count elements of the array _ty in place.
|
||||
template <typename _Ty>
|
||||
OZZ_INLINE void EndianSwap(_Ty* _ty, size_t _count) {
|
||||
EndianSwapper<_Ty>::Swap(_ty, _count);
|
||||
}
|
||||
|
||||
// Helper function that swaps _ty in place.
|
||||
template <typename _Ty>
|
||||
OZZ_INLINE _Ty EndianSwap(_Ty _ty) {
|
||||
return EndianSwapper<_Ty>::Swap(_ty);
|
||||
}
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_ENDIANNESS_H_
|
||||
@@ -0,0 +1,175 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_GTEST_HELPER_H_
|
||||
#define OZZ_OZZ_BASE_GTEST_HELPER_H_
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
// EXPECT_ASSERTION expands to real death test if assertions are enabled.
|
||||
// Parameters:
|
||||
// statement - A statement that a macro such as EXPECT_DEATH would test
|
||||
// for program termination.
|
||||
// regex - A regex that a macro such as EXPECT_DEATH would use to test
|
||||
// the output of statement.
|
||||
#ifdef NDEBUG
|
||||
// Expands to nothing if asserts aren't enabled (ie: NDEBUG is defined)
|
||||
#define EXPECT_ASSERTION(_statement, _regex) \
|
||||
do { \
|
||||
} while (void(0), false);
|
||||
#else // NDEBUG
|
||||
#ifdef _WIN32
|
||||
#include <crtdbg.h>
|
||||
|
||||
#include <cstdlib>
|
||||
namespace internal {
|
||||
// Provides a hook during abort to ensure EXIT_FAILURE is returned.
|
||||
inline int AbortHook(int, char*, int*) { exit(EXIT_FAILURE); }
|
||||
} // namespace internal
|
||||
#define EXPECT_ASSERTION(_statement, _regex) \
|
||||
do { \
|
||||
/* During death tests executions:*/ \
|
||||
/* Disables popping message boxes during crt and stl assertions*/ \
|
||||
int old_mode = 0; \
|
||||
(void)old_mode; \
|
||||
_CRT_REPORT_HOOK old_hook = nullptr; \
|
||||
(void)old_hook; \
|
||||
if (testing::internal::GTEST_FLAG(internal_run_death_test).length() > 0) { \
|
||||
old_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); \
|
||||
old_hook = _CrtSetReportHook(&internal::AbortHook); \
|
||||
} \
|
||||
EXPECT_DEATH((void)(_statement), _regex); \
|
||||
if (testing::internal::GTEST_FLAG(internal_run_death_test).length() > 0) { \
|
||||
_CrtSetReportMode(_CRT_ASSERT, old_mode); \
|
||||
(void)_CrtSetReportHook(old_hook); \
|
||||
} \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
#else // _WIN32
|
||||
#define EXPECT_ASSERTION(_statement, _regex) EXPECT_DEATH(_statement, _regex)
|
||||
#endif // _WIN32
|
||||
#endif // NDEBUG
|
||||
|
||||
// EXPECT_EQ_LOG* executes _expression and compares its result with _eq.
|
||||
// While executing _expression, EXPECT_EQ_LOG redirects _output (ex:
|
||||
// std::clog) and then expects that the output matched the regular expression
|
||||
// _re.
|
||||
#define EXPECT_EQ_LOG(_expression, _eq, _output, _re) \
|
||||
do { \
|
||||
internal::RedirectOuputTester tester(_output, _re); \
|
||||
EXPECT_EQ(_expression, _eq); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// There are multiple declinations EXPECT_EQ_LOG*, to match with clog, cerr and
|
||||
// cout outputs, and verbose level option.
|
||||
|
||||
// Specialises EXPECT_EQ_LOG* for verbose clog output type.
|
||||
#define EXPECT_EQ_LOG_LOGV(_expression, _eq, _re) \
|
||||
EXPECT_EQ_LOG(_expression, _eq, std::clog, \
|
||||
ozz::log::kVerbose <= ozz::log::GetLevel() ? _re : nullptr)
|
||||
|
||||
// Specialises EXPECT_EQ_LOG* for standard clog output type.
|
||||
#define EXPECT_EQ_LOG_LOG(_expression, _eq, _re) \
|
||||
EXPECT_EQ_LOG(_expression, _eq, std::clog, \
|
||||
ozz::log::kStandard <= ozz::log::GetLevel() ? _re : nullptr)
|
||||
|
||||
// Specialises EXPECT_EQ_LOG* for standard cout output type.
|
||||
#define EXPECT_EQ_LOG_OUT(_expression, _eq, _re) \
|
||||
EXPECT_EQ_LOG(_expression, _eq, std::cout, \
|
||||
ozz::log::kStandard <= ozz::log::GetLevel() ? _re : nullptr)
|
||||
|
||||
// Specialises EXPECT_EQ_LOG* for standard cerr output type.
|
||||
#define EXPECT_EQ_LOG_ERR(_expression, _eq, _re) \
|
||||
EXPECT_EQ_LOG(_expression, _eq, std::cerr, \
|
||||
ozz::log::kStandard <= ozz::log::GetLevel() ? _re : nullptr)
|
||||
|
||||
// EXPECT_EQ_LOG* executes _expression while redirecting _output (ex:
|
||||
// std::clog) and then expects that the output matched the regular expression
|
||||
// _re.
|
||||
#define EXPECT_LOG(_expression, _output, _re) \
|
||||
do { \
|
||||
internal::RedirectOuputTester tester(_output, _re); \
|
||||
(_expression); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// There are multiple declinations EXPECT_LOG*, to match with clog, cerr and
|
||||
// cout outputs, and verbose level option.
|
||||
|
||||
// Specialises EXPECT_LOG* for verbose clog output type.
|
||||
#define EXPECT_LOG_LOGV(_expression, _re) \
|
||||
EXPECT_LOG(_expression, std::clog, \
|
||||
ozz::log::kVerbose <= ozz::log::GetLevel() ? _re : nullptr)
|
||||
|
||||
// Specialises EXPECT_LOG* for standard clog output type.
|
||||
#define EXPECT_LOG_LOG(_expression, _re) \
|
||||
EXPECT_LOG(_expression, std::clog, \
|
||||
ozz::log::kStandard <= ozz::log::GetLevel() ? _re : nullptr)
|
||||
|
||||
// Specialises EXPECT_LOG* for standard cout output type.
|
||||
#define EXPECT_LOG_OUT(_expression, _re) \
|
||||
EXPECT_LOG(_expression, std::cout, \
|
||||
ozz::log::kStandard <= ozz::log::GetLevel() ? _re : nullptr)
|
||||
|
||||
// Specialises EXPECT_LOG* for standard cerr output type.
|
||||
#define EXPECT_LOG_ERR(_expression, _re) \
|
||||
EXPECT_LOG(_expression, std::cerr, \
|
||||
ozz::log::kStandard <= ozz::log::GetLevel() ? _re : nullptr)
|
||||
|
||||
namespace internal {
|
||||
class RedirectOuputTester {
|
||||
public:
|
||||
// Specify a nullptr _regex to test an empty output
|
||||
RedirectOuputTester(std::ostream& _ostream, const char* _regex)
|
||||
: ostream_(_ostream), old_(_ostream.rdbuf()), regex_(_regex) {
|
||||
// Redirect ostream_ buffer.
|
||||
ostream_.rdbuf(redirect_.rdbuf());
|
||||
}
|
||||
~RedirectOuputTester() {
|
||||
if (regex_) {
|
||||
EXPECT_TRUE(::testing::internal::RE::PartialMatch(redirect_.str().c_str(),
|
||||
regex_));
|
||||
} else {
|
||||
EXPECT_EQ(redirect_.str().size(), 0u);
|
||||
}
|
||||
// Restore ostream_ buffer.
|
||||
ostream_.rdbuf(old_);
|
||||
// finally outputs everything temporary redirected.
|
||||
ostream_ << redirect_.str();
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostream& ostream_;
|
||||
std::streambuf* old_;
|
||||
const char* regex_;
|
||||
std::stringstream redirect_;
|
||||
};
|
||||
} // namespace internal
|
||||
#endif // OZZ_OZZ_BASE_GTEST_HELPER_H_
|
||||
@@ -0,0 +1,440 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_IO_ARCHIVE_H_
|
||||
#define OZZ_OZZ_BASE_IO_ARCHIVE_H_
|
||||
|
||||
// Provides input (IArchive) and output (OArchive) serialization containers.
|
||||
// Archive are similar to c++ iostream. Data can be saved to a OArchive with
|
||||
// the << operator, or loaded from a IArchive with the >> operator.
|
||||
// Primitive data types are simply saved/loaded to/from archives, while struct
|
||||
// and class are saved/loaded through Save/Load intrusive or non-intrusive
|
||||
// functions:
|
||||
// - The intrusive function prototypes are "void Save(ozz::io::OArchive*) const"
|
||||
// and "void Load(ozz::io::IArchive*)".
|
||||
// - The non-intrusive functions allow to work on arrays of objects. They must
|
||||
// be implemented in ozz::io namespace, by specializing the following template
|
||||
// struct:
|
||||
// template <typename _Ty>
|
||||
// struct Extern {
|
||||
// static void Save(OArchive& _archive, const _Ty* _ty, size_t _count);
|
||||
// static void Load(IArchive& _archive, _Ty* _ty, size_t _count,
|
||||
// uint32_t _version);
|
||||
// };
|
||||
//
|
||||
// Arrays of struct/class or primitive types can be saved/loaded with the
|
||||
// helper function ozz::io::MakeArray() that is then streamed in or out using
|
||||
// << and >> archive operators: archive << ozz::io::MakeArray(my_array, count);
|
||||
//
|
||||
// Versioning can be done using OZZ_IO_TYPE_VERSION macros. Type version
|
||||
// is saved in the OArchive, and is given back to Load functions to allow to
|
||||
// manually handle version modifications. Versioning can be disabled using
|
||||
// OZZ_IO_TYPE_NOT_VERSIONABLE like macros. It can not be re-enabled afterward.
|
||||
//
|
||||
// Objects can be assigned a tag using OZZ_IO_TYPE_TAG macros. A tag allows to
|
||||
// check the type of the next object to read from an archive. An automatic
|
||||
// assertion check is performed for each object that has a tag. It can also be
|
||||
// done manually to ensure an archive has the expected content.
|
||||
//
|
||||
// Endianness (big-endian or little-endian) can be specified while constructing
|
||||
// an output archive (ozz::io::OArchive). Input archives automatically handle
|
||||
// endianness conversion if the native platform endian mode differs from the
|
||||
// archive one.
|
||||
//
|
||||
// IArchive and OArchive expect valid streams as argument, respectively opened
|
||||
// for reading and writing. Archives do NOT perform error detection while
|
||||
// reading or writing. All errors are considered programming errors. This leads
|
||||
// to the following assertions on the user side:
|
||||
// - When writing: the stream must be big (or grow-able) enough to support the
|
||||
// data being written.
|
||||
// - When reading: Stream's tell (position in the stream) must match the object
|
||||
// being read. To help with this requirement, archives provide a tag mechanism
|
||||
// that allows to check the tag (ie the type) of the next object to read. Stream
|
||||
// integrity, like data corruption or file truncation, must also be validated on
|
||||
// the user side.
|
||||
|
||||
#include "ozz/base/endianness.h"
|
||||
#include "ozz/base/io/stream.h"
|
||||
#include "ozz/base/platform.h"
|
||||
#include "ozz/base/span.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cassert>
|
||||
|
||||
#include "ozz/base/io/archive_traits.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace io {
|
||||
namespace internal {
|
||||
// Defines Tagger helper object struct.
|
||||
// The boolean template argument is used to automatically select a template
|
||||
// specialization, whether _Ty has a tag or not.
|
||||
template <typename _Ty,
|
||||
bool _HasTag = internal::Tag<const _Ty>::kTagLength != 0>
|
||||
struct Tagger;
|
||||
} // namespace internal
|
||||
|
||||
// Implements output archive concept used to save/serialize data from a Stream.
|
||||
// The output endianness mode is set at construction time. It is written to the
|
||||
// stream to allow the IArchive to perform the required conversion to the native
|
||||
// endianness mode while reading.
|
||||
class OArchive {
|
||||
public:
|
||||
// Constructs an output archive from the Stream _stream that must be valid
|
||||
// and opened for writing.
|
||||
explicit OArchive(Stream* _stream,
|
||||
Endianness _endianness = GetNativeEndianness());
|
||||
|
||||
// Returns true if an endian swap is required while writing.
|
||||
bool endian_swap() const { return endian_swap_; }
|
||||
|
||||
// Saves _size bytes of binary data from _data.
|
||||
size_t SaveBinary(const void* _data, size_t _size) {
|
||||
return stream_->Write(_data, _size);
|
||||
}
|
||||
|
||||
// Class type saving.
|
||||
template <typename _Ty>
|
||||
void operator<<(const _Ty& _ty) {
|
||||
internal::Tagger<const _Ty>::Write(*this);
|
||||
SaveVersion<_Ty>();
|
||||
Extern<_Ty>::Save(*this, &_ty, 1);
|
||||
}
|
||||
|
||||
// Primitive type saving.
|
||||
#define OZZ_IO_PRIMITIVE_TYPE(_type) \
|
||||
void operator<<(_type _v) { \
|
||||
_type v = endian_swap_ ? EndianSwapper<_type>::Swap(_v) : _v; \
|
||||
OZZ_IF_DEBUG(size_t size =) stream_->Write(&v, sizeof(v)); \
|
||||
assert(size == sizeof(v)); \
|
||||
}
|
||||
|
||||
OZZ_IO_PRIMITIVE_TYPE(char)
|
||||
OZZ_IO_PRIMITIVE_TYPE(int8_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(uint8_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(int16_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(uint16_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(int32_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(uint32_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(int64_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(uint64_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(bool)
|
||||
OZZ_IO_PRIMITIVE_TYPE(float)
|
||||
#undef OZZ_IO_PRIMITIVE_TYPE
|
||||
|
||||
// Returns output stream.
|
||||
Stream* stream() const { return stream_; }
|
||||
|
||||
private:
|
||||
template <typename _Ty>
|
||||
void SaveVersion() {
|
||||
// Compilation could fail here if the version is not defined for _Ty, or if
|
||||
// the .h file containing its definition is not included by the caller of
|
||||
// this function.
|
||||
if (void(0), internal::Version<const _Ty>::kValue != 0) {
|
||||
uint32_t version = internal::Version<const _Ty>::kValue;
|
||||
*this << version;
|
||||
}
|
||||
}
|
||||
|
||||
// The output stream.
|
||||
Stream* stream_;
|
||||
|
||||
// Endian swap state, true if a conversion is required while writing.
|
||||
bool endian_swap_;
|
||||
};
|
||||
|
||||
// Implements input archive concept used to load/de-serialize data to a Stream.
|
||||
// Endianness conversions are automatically performed according to the Archive
|
||||
// and the native formats.
|
||||
class IArchive {
|
||||
public:
|
||||
// Constructs an input archive from the Stream _stream that must be opened for
|
||||
// reading, at the same tell (position in the stream) as when it was passed to
|
||||
// the OArchive.
|
||||
explicit IArchive(Stream* _stream);
|
||||
|
||||
// Returns true if an endian swap is required while reading.
|
||||
bool endian_swap() const { return endian_swap_; }
|
||||
|
||||
// Loads _size bytes of binary data to _data.
|
||||
size_t LoadBinary(void* _data, size_t _size) {
|
||||
return stream_->Read(_data, _size);
|
||||
}
|
||||
|
||||
// Class type loading.
|
||||
template <typename _Ty>
|
||||
void operator>>(_Ty& _ty) {
|
||||
// Only uses tag validation for assertions, as reading cannot fail.
|
||||
OZZ_IF_DEBUG(bool valid =) internal::Tagger<const _Ty>::Validate(*this);
|
||||
assert(valid && "Type tag does not match archive content.");
|
||||
|
||||
// Loads instance.
|
||||
uint32_t version = LoadVersion<_Ty>();
|
||||
Extern<_Ty>::Load(*this, &_ty, 1, version);
|
||||
}
|
||||
|
||||
// Primitive type loading.
|
||||
#define OZZ_IO_PRIMITIVE_TYPE(_type) \
|
||||
void operator>>(_type& _v) { \
|
||||
_type v; \
|
||||
OZZ_IF_DEBUG(size_t size =) stream_->Read(&v, sizeof(v)); \
|
||||
assert(size == sizeof(v)); \
|
||||
_v = endian_swap_ ? EndianSwapper<_type>::Swap(v) : v; \
|
||||
}
|
||||
|
||||
OZZ_IO_PRIMITIVE_TYPE(char)
|
||||
OZZ_IO_PRIMITIVE_TYPE(int8_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(uint8_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(int16_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(uint16_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(int32_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(uint32_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(int64_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(uint64_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(bool)
|
||||
OZZ_IO_PRIMITIVE_TYPE(float)
|
||||
#undef OZZ_IO_PRIMITIVE_TYPE
|
||||
|
||||
template <typename _Ty>
|
||||
bool TestTag() {
|
||||
// Only tagged types can be tested. If compilations fails here, it can
|
||||
// mean the file containing tag declaration is not included.
|
||||
static_assert(internal::Tag<const _Ty>::kTagLength != 0,
|
||||
"Tag unknown for type.");
|
||||
|
||||
const int tell = stream_->Tell();
|
||||
bool valid = internal::Tagger<const _Ty>::Validate(*this);
|
||||
stream_->Seek(tell, Stream::kSet); // Rewinds before the tag test.
|
||||
return valid;
|
||||
}
|
||||
|
||||
// Returns input stream.
|
||||
Stream* stream() const { return stream_; }
|
||||
|
||||
private:
|
||||
template <typename _Ty>
|
||||
uint32_t LoadVersion() {
|
||||
uint32_t version = 0;
|
||||
if (void(0), internal::Version<const _Ty>::kValue != 0) {
|
||||
*this >> version;
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
// The input stream.
|
||||
Stream* stream_;
|
||||
|
||||
// Endian swap state, true if a conversion is required while reading.
|
||||
bool endian_swap_;
|
||||
};
|
||||
|
||||
// Primitive type are not versionable.
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(char)
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(int8_t)
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(uint8_t)
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(int16_t)
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(uint16_t)
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(int32_t)
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(uint32_t)
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(int64_t)
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(uint64_t)
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(bool)
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(float)
|
||||
|
||||
// Default loading and saving external implementation.
|
||||
template <typename _Ty>
|
||||
struct Extern {
|
||||
inline static void Save(OArchive& _archive, const _Ty* _ty, size_t _count) {
|
||||
for (size_t i = 0; i < _count; ++i) {
|
||||
_ty[i].Save(_archive);
|
||||
}
|
||||
}
|
||||
inline static void Load(IArchive& _archive, _Ty* _ty, size_t _count,
|
||||
uint32_t _version) {
|
||||
for (size_t i = 0; i < _count; ++i) {
|
||||
_ty[i].Load(_archive, _version);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Wrapper for dynamic array serialization.
|
||||
// Must be used through ozz::io::MakeArray.
|
||||
namespace internal {
|
||||
template <typename _Ty>
|
||||
struct Array {
|
||||
OZZ_INLINE void Save(OArchive& _archive) const {
|
||||
ozz::io::Extern<_Ty>::Save(_archive, array, count);
|
||||
}
|
||||
OZZ_INLINE void Load(IArchive& _archive, uint32_t _version) const {
|
||||
ozz::io::Extern<_Ty>::Load(_archive, array, count, _version);
|
||||
}
|
||||
_Ty* array;
|
||||
size_t count;
|
||||
};
|
||||
// Specialize for const _Ty which can only be saved.
|
||||
template <typename _Ty>
|
||||
struct Array<const _Ty> {
|
||||
OZZ_INLINE void Save(OArchive& _archive) const {
|
||||
ozz::io::Extern<_Ty>::Save(_archive, array, count);
|
||||
}
|
||||
const _Ty* array;
|
||||
size_t count;
|
||||
};
|
||||
|
||||
// Array copies version from the type it contains.
|
||||
// Definition of Array of _Ty version: _Ty version.
|
||||
template <typename _Ty>
|
||||
struct Version<const Array<_Ty>> {
|
||||
enum { kValue = Version<const _Ty>::kValue };
|
||||
};
|
||||
|
||||
// Specializes Array Save/Load for primitive types.
|
||||
#define OZZ_IO_PRIMITIVE_TYPE(_type) \
|
||||
template <> \
|
||||
inline void Array<const _type>::Save(OArchive& _archive) const { \
|
||||
if (_archive.endian_swap()) { \
|
||||
/* Save element by element as swapping in place the whole buffer is*/ \
|
||||
/* not possible.*/ \
|
||||
for (size_t i = 0; i < count; ++i) { \
|
||||
_archive << array[i]; \
|
||||
} \
|
||||
} else { \
|
||||
OZZ_IF_DEBUG(size_t size =) \
|
||||
_archive.SaveBinary(array, count * sizeof(_type)); \
|
||||
assert(size == count * sizeof(_type)); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
template <> \
|
||||
inline void Array<_type>::Save(OArchive& _archive) const { \
|
||||
if (_archive.endian_swap()) { \
|
||||
/* Save element by element as swapping in place the whole buffer is*/ \
|
||||
/* not possible.*/ \
|
||||
for (size_t i = 0; i < count; ++i) { \
|
||||
_archive << array[i]; \
|
||||
} \
|
||||
} else { \
|
||||
OZZ_IF_DEBUG(size_t size =) \
|
||||
_archive.SaveBinary(array, count * sizeof(_type)); \
|
||||
assert(size == count * sizeof(_type)); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
template <> \
|
||||
inline void Array<_type>::Load(IArchive& _archive, uint32_t /*_version*/) \
|
||||
const { \
|
||||
OZZ_IF_DEBUG(size_t size =) \
|
||||
_archive.LoadBinary(array, count * sizeof(_type)); \
|
||||
assert(size == count * sizeof(_type)); \
|
||||
if (_archive.endian_swap()) { /*Can swap in-place.*/ \
|
||||
EndianSwapper<_type>::Swap(array, count); \
|
||||
} \
|
||||
}
|
||||
|
||||
OZZ_IO_PRIMITIVE_TYPE(char)
|
||||
OZZ_IO_PRIMITIVE_TYPE(int8_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(uint8_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(int16_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(uint16_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(int32_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(uint32_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(int64_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(uint64_t)
|
||||
OZZ_IO_PRIMITIVE_TYPE(bool)
|
||||
OZZ_IO_PRIMITIVE_TYPE(float)
|
||||
#undef OZZ_IO_PRIMITIVE_TYPE
|
||||
} // namespace internal
|
||||
|
||||
// Utility function that instantiates Array wrapper.
|
||||
template <typename _Ty>
|
||||
OZZ_INLINE const internal::Array<_Ty> MakeArray(_Ty* _array, size_t _count) {
|
||||
const internal::Array<_Ty> array = {_array, _count};
|
||||
return array;
|
||||
}
|
||||
template <typename _Ty>
|
||||
OZZ_INLINE const internal::Array<const _Ty> MakeArray(const _Ty* _array,
|
||||
size_t _count) {
|
||||
const internal::Array<const _Ty> array = {_array, _count};
|
||||
return array;
|
||||
}
|
||||
template <typename _Ty>
|
||||
OZZ_INLINE const internal::Array<_Ty> MakeArray(span<_Ty> _array) {
|
||||
const internal::Array<_Ty> array = {_array.data(), _array.size()};
|
||||
return array;
|
||||
}
|
||||
template <typename _Ty>
|
||||
OZZ_INLINE const internal::Array<const _Ty> MakeArray(span<const _Ty> _array) {
|
||||
const internal::Array<const _Ty> array = {_array.data(), _array.size()};
|
||||
return array;
|
||||
}
|
||||
template <typename _Ty, size_t _count>
|
||||
OZZ_INLINE const internal::Array<_Ty> MakeArray(_Ty (&_array)[_count]) {
|
||||
const internal::Array<_Ty> array = {_array, _count};
|
||||
return array;
|
||||
}
|
||||
template <typename _Ty, size_t _count>
|
||||
OZZ_INLINE const internal::Array<const _Ty> MakeArray(
|
||||
const _Ty (&_array)[_count]) {
|
||||
const internal::Array<const _Ty> array = {_array, _count};
|
||||
return array;
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
// Specialization of the Tagger helper for tagged types.
|
||||
template <typename _Ty>
|
||||
struct Tagger<_Ty, true> {
|
||||
static void Write(OArchive& _archive) {
|
||||
typedef internal::Tag<const _Ty> Tag;
|
||||
OZZ_IF_DEBUG(size_t size =)
|
||||
_archive.SaveBinary(Tag::Get(), Tag::kTagLength);
|
||||
assert(size == Tag::kTagLength);
|
||||
}
|
||||
static bool Validate(IArchive& _archive) {
|
||||
typedef internal::Tag<const _Ty> Tag;
|
||||
char buf[Tag::kTagLength];
|
||||
if (Tag::kTagLength != _archive.LoadBinary(buf, Tag::kTagLength)) {
|
||||
return false;
|
||||
}
|
||||
const char* tag = Tag::Get();
|
||||
size_t i = 0;
|
||||
for (; i < Tag::kTagLength && buf[i] == tag[i]; ++i) {
|
||||
}
|
||||
return i == Tag::kTagLength;
|
||||
}
|
||||
};
|
||||
|
||||
// Specialization of the Tagger helper for types with no tag.
|
||||
template <typename _Ty>
|
||||
struct Tagger<_Ty, false> {
|
||||
static void Write(OArchive& /*_archive*/) {}
|
||||
static bool Validate(IArchive& /*_archive*/) { return true; }
|
||||
};
|
||||
} // namespace internal
|
||||
} // namespace io
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_IO_ARCHIVE_H_
|
||||
@@ -0,0 +1,220 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_IO_ARCHIVE_TRAITS_H_
|
||||
#define OZZ_OZZ_BASE_IO_ARCHIVE_TRAITS_H_
|
||||
|
||||
// Provides traits for customizing archive serialization properties: version,
|
||||
// tag... See archive.h for more details.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstddef>
|
||||
|
||||
namespace ozz {
|
||||
namespace io {
|
||||
|
||||
// Forward declaration of archive types.
|
||||
class OArchive;
|
||||
class IArchive;
|
||||
|
||||
// Default loading and saving external declaration.
|
||||
// Those template implementations aim to be specialized at compilation time by
|
||||
// non-member Load and save functions. For example the specialization of the
|
||||
// Save() function for a type Type is:
|
||||
// void Save(OArchive& _archive, const Extrusive* _test, size_t _count) {
|
||||
// }
|
||||
// The Load() function receives the version _version of type _Ty at the time the
|
||||
// archive was saved.
|
||||
// This uses polymorphism rather than template specialization to avoid
|
||||
// including the file that contains the template definition.
|
||||
//
|
||||
// This default function call member _Ty::Load/Save function.
|
||||
template <typename _Ty>
|
||||
struct Extern;
|
||||
|
||||
// Declares the current (compile time) version of _type.
|
||||
// This macro must be used inside namespace ozz::io.
|
||||
// Syntax is: OZZ_IO_TYPE_VERSION(46, Foo).
|
||||
#define OZZ_IO_TYPE_VERSION(_version, _type) \
|
||||
static_assert(_version > 0, "Version number must be > 0"); \
|
||||
namespace internal { \
|
||||
template <> \
|
||||
struct Version<const _type> { \
|
||||
enum { kValue = _version }; \
|
||||
}; \
|
||||
} // internal
|
||||
|
||||
// Declares the current (compile time) version of a template _type.
|
||||
// This macro must be used inside namespace ozz::io.
|
||||
// OZZ_IO_TYPE_VERSION_T1(46, typename _T1, Foo<_T1>).
|
||||
#define OZZ_IO_TYPE_VERSION_T1(_version, _arg0, ...) \
|
||||
static_assert(_version > 0, "Version number must be > 0"); \
|
||||
namespace internal { \
|
||||
template <_arg0> \
|
||||
struct Version<const __VA_ARGS__> { \
|
||||
enum { kValue = _version }; \
|
||||
}; \
|
||||
} // internal
|
||||
|
||||
// Declares the current (compile time) version of a template _type.
|
||||
// This macro must be used inside namespace ozz::io.
|
||||
// OZZ_IO_TYPE_VERSION_T2(46, typename _T1, typename _T2, Foo<_T1, _T2>).
|
||||
#define OZZ_IO_TYPE_VERSION_T2(_version, _arg0, _arg1, ...) \
|
||||
static_assert(_version > 0, "Version number must be > 0"); \
|
||||
namespace internal { \
|
||||
template <_arg0, _arg1> \
|
||||
struct Version<const __VA_ARGS__> { \
|
||||
enum { kValue = _version }; \
|
||||
}; \
|
||||
\
|
||||
} // internal
|
||||
|
||||
// Declares the current (compile time) version of a template _type.
|
||||
// This macro must be used inside namespace ozz::io.
|
||||
// OZZ_IO_TYPE_VERSION_T3(
|
||||
// 46, typename _T1, typename _T2, typename _T3, Foo<_T1, _T2, _T3>).
|
||||
#define OZZ_IO_TYPE_VERSION_T3(_version, _arg0, _arg1, _arg2, ...) \
|
||||
static_assert(_version > 0, "Version number must be > 0"); \
|
||||
namespace internal { \
|
||||
template <_arg0, _arg1, _arg2> \
|
||||
struct Version<const __VA_ARGS__> { \
|
||||
enum { kValue = _version }; \
|
||||
}; \
|
||||
\
|
||||
} // internal
|
||||
|
||||
// Declares the current (compile time) version of a template _type.
|
||||
// This macro must be used inside namespace ozz::io.
|
||||
// OZZ_IO_TYPE_VERSION_T4(
|
||||
// 46, typename _T1, typename _T2, typename _T3, typename _T4,
|
||||
// Foo<_T1, _T2, _T3, _T4>).
|
||||
#define OZZ_IO_TYPE_VERSION_T4(_version, _arg0, _arg1, _arg2, _arg3, ...) \
|
||||
static_assert(_version > 0, "Version number must be > 0"); \
|
||||
namespace internal { \
|
||||
template <_arg0, _arg1, _arg2, _arg3> \
|
||||
struct Version<const __VA_ARGS__> { \
|
||||
enum { kValue = _version }; \
|
||||
}; \
|
||||
} // internal
|
||||
|
||||
// Declares that _type is not versionable. Its version number is 0.
|
||||
// Once a type has been declared not versionable, it cannot be changed without
|
||||
// braking versioning.
|
||||
// This macro must be used inside namespace ozz::io.
|
||||
// Syntax is: OZZ_IO_TYPE_NOT_VERSIONABLE(Foo).
|
||||
#define OZZ_IO_TYPE_NOT_VERSIONABLE(_type) \
|
||||
namespace internal { \
|
||||
template <> \
|
||||
struct Version<const _type> { \
|
||||
enum { kValue = 0 }; \
|
||||
}; \
|
||||
} // internal
|
||||
|
||||
// Declares that a template _type is not versionable. Its version number is 0.
|
||||
// Once a type has been declared not versionable, it cannot be changed without
|
||||
// braking versioning.
|
||||
// This macro must be used inside namespace ozz::io.
|
||||
// Syntax is:
|
||||
// OZZ_IO_TYPE_NOT_VERSIONABLE_T1(typename _T1, Foo<_T1>).
|
||||
#define OZZ_IO_TYPE_NOT_VERSIONABLE_T1(_arg0, ...) \
|
||||
namespace internal { \
|
||||
template <_arg0> \
|
||||
struct Version<const __VA_ARGS__> { \
|
||||
enum { kValue = 0 }; \
|
||||
}; \
|
||||
} // internal
|
||||
|
||||
// Decline non-versionable template declaration to 2 template arguments.
|
||||
// Syntax is:
|
||||
// OZZ_IO_TYPE_NOT_VERSIONABLE_T2(typename _T1, typename _T2, Foo<_T1, _T2>).
|
||||
#define OZZ_IO_TYPE_NOT_VERSIONABLE_T2(_arg0, _arg1, ...) \
|
||||
namespace internal { \
|
||||
template <_arg0, _arg1> \
|
||||
struct Version<const __VA_ARGS__> { \
|
||||
enum { kValue = 0 }; \
|
||||
}; \
|
||||
} // internal
|
||||
|
||||
// Decline non-versionable template declaration to 3 template arguments.
|
||||
// Syntax is:
|
||||
// OZZ_IO_TYPE_NOT_VERSIONABLE_T3(
|
||||
// typename _T1, typename _T2, typename _T3, Foo<_T1, _T2, _T3>).
|
||||
#define OZZ_IO_TYPE_NOT_VERSIONABLE_T3(_arg0, _arg1, _arg2, ...) \
|
||||
namespace internal { \
|
||||
template <_arg0, _arg1, _arg2> \
|
||||
struct Version<const __VA_ARGS__> { \
|
||||
enum { kValue = 0 }; \
|
||||
}; \
|
||||
} // internal
|
||||
|
||||
// Decline non-versionable template declaration to 4 template arguments.
|
||||
// Syntax is:
|
||||
// OZZ_IO_TYPE_NOT_VERSIONABLE_T4(
|
||||
// typename _T1, typename _T2, typename _T3, typename _T4,
|
||||
// Foo<_T1, _T2, _T3, _T4>).
|
||||
#define OZZ_IO_TYPE_NOT_VERSIONABLE_T4(_arg0, _arg1, _arg2, _arg3, ...) \
|
||||
namespace internal { \
|
||||
template <_arg0, _arg1, _arg2, _arg3> \
|
||||
struct Version<const __VA_ARGS__> { \
|
||||
enum { kValue = 0 }; \
|
||||
}; \
|
||||
} // internal
|
||||
|
||||
// Declares the tag of a template _type.
|
||||
// A tag is a c-string that can be used to check the type (through its tag) of
|
||||
// the next object to be read from an archive. If no tag is defined, then no
|
||||
// check is performed.
|
||||
// This macro must be used inside namespace ozz::io.
|
||||
// OZZ_IO_TYPE_TAG("Foo", Foo).
|
||||
#define OZZ_IO_TYPE_TAG(_tag, _type) \
|
||||
namespace internal { \
|
||||
template <> \
|
||||
struct Tag<const _type> { \
|
||||
/* Length includes null terminated character to detect partial */ \
|
||||
/* tag mapping.*/ \
|
||||
enum { kTagLength = OZZ_ARRAY_SIZE(_tag) }; \
|
||||
static const char* Get() { return _tag; } \
|
||||
}; \
|
||||
} // internal
|
||||
|
||||
namespace internal {
|
||||
// Definition of version specializable template struct.
|
||||
// There's no default implementation in order to force user to define it, which
|
||||
// in turn forces those who want to serialize an object to include the file that
|
||||
// defines it's version. This helps with detecting issues at compile time.
|
||||
template <typename _Ty>
|
||||
struct Version;
|
||||
|
||||
// Defines default tag value, which is disabled.
|
||||
template <typename _Ty>
|
||||
struct Tag {
|
||||
enum { kTagLength = 0 };
|
||||
};
|
||||
} // namespace internal
|
||||
} // namespace io
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_IO_ARCHIVE_TRAITS_H_
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_IO_STREAM_H_
|
||||
#define OZZ_OZZ_BASE_IO_STREAM_H_
|
||||
|
||||
// Provides Stream interface used to read/write a memory buffer or a file with
|
||||
// Crt fread/fwrite/fseek/ftell like functions.
|
||||
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace ozz {
|
||||
namespace io {
|
||||
|
||||
// Declares a stream access interface that conforms with CRT FILE API.
|
||||
// This interface should be used to remap io operations.
|
||||
class Stream {
|
||||
public:
|
||||
// Tests whether a file is opened.
|
||||
virtual bool opened() const = 0;
|
||||
|
||||
// Reads _size bytes of data to _buffer from the stream. _buffer must be big
|
||||
// enough to store _size bytes. The position indicator of the stream is
|
||||
// advanced by the total amount of bytes read.
|
||||
// Returns the number of bytes actually read, which may be less than _size.
|
||||
virtual size_t Read(void* _buffer, size_t _size) = 0;
|
||||
|
||||
// Writes _size bytes of data from _buffer to the stream. The position
|
||||
// indicator of the stream is advanced by the total number of bytes written.
|
||||
// Returns the number of bytes actually written, which may be less than _size.
|
||||
virtual size_t Write(const void* _buffer, size_t _size) = 0;
|
||||
|
||||
// Declares seeking origin enumeration.
|
||||
enum Origin {
|
||||
kCurrent, // Current position of the stream pointer.
|
||||
kEnd, // End of stream.
|
||||
kSet, // Beginning of stream.
|
||||
};
|
||||
// Sets the position indicator associated with the stream to a new position
|
||||
// defined by adding _offset to a reference position specified by _origin.
|
||||
// Returns a zero value if successful, otherwise returns a non-zero value.
|
||||
virtual int Seek(int _offset, Origin _origin) = 0;
|
||||
|
||||
// Returns the current value of the position indicator of the stream.
|
||||
// Returns -1 if an error occurs.
|
||||
virtual int Tell() const = 0;
|
||||
|
||||
// Returns the current size of the stream.
|
||||
virtual size_t Size() const = 0;
|
||||
|
||||
protected:
|
||||
Stream() {}
|
||||
|
||||
// Required virtual destructor.
|
||||
virtual ~Stream() {}
|
||||
|
||||
private:
|
||||
Stream(const Stream&);
|
||||
void operator=(const Stream&);
|
||||
};
|
||||
|
||||
// Implements Stream of type File.
|
||||
class File : public Stream {
|
||||
public:
|
||||
// Test if a file at path _filename exists.
|
||||
// Note that this function is costly. If you aim to open the file right after,
|
||||
// then open it and use File::opened() to test if it's actually existing.
|
||||
static bool Exist(const char* _filename);
|
||||
|
||||
// Open a file at path _filename with mode * _mode, in conformance with fopen
|
||||
// specifications.
|
||||
// Use opened() function to test opening result.
|
||||
File(const char* _filename, const char* _mode);
|
||||
|
||||
// Gives _file ownership to the FileStream, which will be in charge of closing
|
||||
// it. _file must be nullptr or a valid std::FILE pointer.
|
||||
explicit File(void* _file);
|
||||
|
||||
// Close the file if it is opened.
|
||||
virtual ~File();
|
||||
|
||||
// Close the file if it is opened.
|
||||
void Close();
|
||||
|
||||
// See Stream::opened for details.
|
||||
virtual bool opened() const;
|
||||
|
||||
// See Stream::Read for details.
|
||||
virtual size_t Read(void* _buffer, size_t _size);
|
||||
|
||||
// See Stream::Write for details.
|
||||
virtual size_t Write(const void* _buffer, size_t _size);
|
||||
|
||||
// See Stream::Seek for details.
|
||||
virtual int Seek(int _offset, Origin _origin);
|
||||
|
||||
// See Stream::Tell for details.
|
||||
virtual int Tell() const;
|
||||
|
||||
// See Stream::Tell for details.
|
||||
virtual size_t Size() const;
|
||||
|
||||
private:
|
||||
// The CRT file pointer.
|
||||
void* file_;
|
||||
};
|
||||
|
||||
// Implements an in-memory Stream. Allows to use a memory buffer as a Stream.
|
||||
// The opening mode is equivalent to fopen w+b (binary read/write).
|
||||
class MemoryStream : public Stream {
|
||||
public:
|
||||
// Construct an empty memory stream opened in w+b mode.
|
||||
MemoryStream();
|
||||
|
||||
// Closes the stream and deallocates memory buffer.
|
||||
virtual ~MemoryStream();
|
||||
|
||||
// See Stream::opened for details.
|
||||
virtual bool opened() const;
|
||||
|
||||
// See Stream::Read for details.
|
||||
virtual size_t Read(void* _buffer, size_t _size);
|
||||
|
||||
// See Stream::Write for details.
|
||||
virtual size_t Write(const void* _buffer, size_t _size);
|
||||
|
||||
// See Stream::Seek for details.
|
||||
virtual int Seek(int _offset, Origin _origin);
|
||||
|
||||
// See Stream::Tell for details.
|
||||
virtual int Tell() const;
|
||||
|
||||
// See Stream::Tell for details.
|
||||
virtual size_t Size() const;
|
||||
|
||||
private:
|
||||
// Resizes buffers size to _size bytes. If _size is less than the actual
|
||||
// buffer size, then it remains unchanged.
|
||||
// Returns true if the buffer can contains _size bytes.
|
||||
bool Resize(size_t _size);
|
||||
|
||||
// Size of the buffer increment.
|
||||
static const size_t kBufferSizeIncrement;
|
||||
|
||||
// Maximum stream size.
|
||||
static const size_t kMaxSize;
|
||||
|
||||
// Buffer of data.
|
||||
char* buffer_;
|
||||
|
||||
// The size of the buffer, which is greater or equal to the size of the data
|
||||
// it contains (end_).
|
||||
size_t alloc_size_;
|
||||
|
||||
// The effective size of the data in the buffer.
|
||||
int end_;
|
||||
|
||||
// The cursor position in the buffer of data.
|
||||
int tell_;
|
||||
};
|
||||
} // namespace io
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_IO_STREAM_H_
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_LOG_H_
|
||||
#define OZZ_OZZ_BASE_LOG_H_
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// MSVC includes <cstring> from <iostream> but not gcc.
|
||||
// So it is included here to ensure a portable behavior.
|
||||
#include <cstring>
|
||||
|
||||
// Proposes a logging interface that redirects logs to std::cout, clog and cerr
|
||||
// output streams. This interface adds a logging level functionality (kSilent,
|
||||
// kStandard, kVerbose) to the std API, which can be set using
|
||||
// ozz::log::GetLevel function.
|
||||
// Usage conforms to std stream usage: ozz::log::Log() << "something to log."...
|
||||
|
||||
namespace ozz {
|
||||
namespace log {
|
||||
|
||||
enum Level {
|
||||
kSilent, // No output at all, even errors are muted.
|
||||
kStandard, // Default output level.
|
||||
kVerbose, // Most verbose output level.
|
||||
};
|
||||
|
||||
// Sets the global logging level.
|
||||
Level SetLevel(Level _level);
|
||||
|
||||
// Gets the global logging level.
|
||||
Level GetLevel();
|
||||
|
||||
// Implements logging base class.
|
||||
// This class is not intended to be used publicly, it is derived by user
|
||||
// classes LogV, Log, Out, Err...
|
||||
// Forwards ostream::operator << to a standard ostream or a silent
|
||||
// ostringstream according to the logging level at construction time.
|
||||
class Logger {
|
||||
public:
|
||||
// Forwards ostream::operator << for any type.
|
||||
template <typename _T>
|
||||
std::ostream& operator<<(const _T& _t) {
|
||||
return stream_ << _t;
|
||||
}
|
||||
// Forwards ostream::operator << for modifiers.
|
||||
std::ostream& operator<<(std::ostream& (*_Pfn)(std::ostream&)) {
|
||||
return ((*_Pfn)(stream_));
|
||||
}
|
||||
// Implicit cast operator.
|
||||
operator std::ostream&() const { return stream_; }
|
||||
|
||||
// Explicit cast function.
|
||||
std::ostream& stream() const { return stream_; }
|
||||
|
||||
protected:
|
||||
// Specifies the global stream and the output level.
|
||||
// Logging levels allows to select _stream or a "silent" stream according to
|
||||
// the current global logging level.
|
||||
Logger(std::ostream& _stream, Level _level);
|
||||
|
||||
// Destructor, deletes the internal "silent" stream.
|
||||
~Logger();
|
||||
|
||||
private:
|
||||
// Disables copy and assignment.
|
||||
Logger(const Logger&);
|
||||
void operator=(Logger&);
|
||||
|
||||
// Selected output stream.
|
||||
std::ostream& stream_;
|
||||
|
||||
// Stores whether the stream is local one, in which case it must be deleted
|
||||
// in the destructor.
|
||||
bool local_stream_;
|
||||
};
|
||||
|
||||
// Logs verbose output to the standard error stream (std::clog).
|
||||
// Enabled if logging level is Verbose.
|
||||
class LogV : public Logger {
|
||||
public:
|
||||
LogV();
|
||||
};
|
||||
|
||||
// Logs output to the standard error stream (std::clog).
|
||||
// Enabled if logging level is not Silent.
|
||||
class Log : public Logger {
|
||||
public:
|
||||
Log();
|
||||
};
|
||||
|
||||
// Logs output to the standard output (std::cout).
|
||||
// Enabled if logging level is not Silent.
|
||||
class Out : public Logger {
|
||||
public:
|
||||
Out();
|
||||
};
|
||||
|
||||
// Logs error to the standard error stream (std::cerr).
|
||||
// Enabled if logging level is not Silent.
|
||||
class Err : public Logger {
|
||||
public:
|
||||
Err();
|
||||
};
|
||||
|
||||
// RAII helper that modifies float logging precision, and restores default
|
||||
// settings when exiting scope.
|
||||
// User is reponsible for making sure stream still exist upon RAII destruction.
|
||||
// See std::setprecision() for more details.
|
||||
class FloatPrecision {
|
||||
public:
|
||||
FloatPrecision(const Logger& _logger, int _precision);
|
||||
~FloatPrecision();
|
||||
|
||||
private:
|
||||
FloatPrecision(FloatPrecision const&);
|
||||
void operator=(FloatPrecision const&);
|
||||
|
||||
// Original precision and format.
|
||||
const std::streamsize precision_;
|
||||
const std::ios_base::fmtflags format_;
|
||||
|
||||
// Stream on which original precision must be restored.
|
||||
std::ostream& stream_;
|
||||
};
|
||||
} // namespace log
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_LOG_H_
|
||||
@@ -0,0 +1,84 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_MATHS_BOX_H_
|
||||
#define OZZ_OZZ_BASE_MATHS_BOX_H_
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "ozz/base/maths/vec_float.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace math {
|
||||
|
||||
// Matrix forward declaration.
|
||||
struct Float4x4;
|
||||
|
||||
// Defines an axis aligned box.
|
||||
struct Box {
|
||||
// Constructs an invalid box.
|
||||
Box();
|
||||
|
||||
// Constructs a box with the specified _min and _max bounds.
|
||||
Box(const Float3& _min, const Float3& _max) : min(_min), max(_max) {}
|
||||
|
||||
// Constructs the smallest box that contains the _count points _points.
|
||||
// _stride is the number of bytes between points.
|
||||
explicit Box(const Float3& _point) : min(_point), max(_point) {}
|
||||
|
||||
// Constructs the smallest box that contains the _count points _points.
|
||||
// _stride is the number of bytes between points, it must be greater or
|
||||
// equal to sizeof(Float3).
|
||||
Box(const Float3* _points, size_t _stride, size_t _count);
|
||||
|
||||
// Tests whether *this is a valid box.
|
||||
bool is_valid() const { return min <= max; }
|
||||
|
||||
// Tests whether _p is within box bounds.
|
||||
bool is_inside(const Float3& _p) const { return _p >= min && _p <= max; }
|
||||
|
||||
// Box's min and max bounds.
|
||||
Float3 min;
|
||||
Float3 max;
|
||||
};
|
||||
|
||||
// Merges two boxes _a and _b.
|
||||
// Both _a and _b can be invalid.
|
||||
OZZ_INLINE Box Merge(const Box& _a, const Box& _b) {
|
||||
if (!_a.is_valid()) {
|
||||
return _b;
|
||||
} else if (!_b.is_valid()) {
|
||||
return _a;
|
||||
}
|
||||
return Box(Min(_a.min, _b.min), Max(_a.max, _b.max));
|
||||
}
|
||||
|
||||
// Compute box transformation by a matrix.
|
||||
Box TransformBox(const Float4x4& _matrix, const Box& _box);
|
||||
} // namespace math
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_MATHS_BOX_H_
|
||||
@@ -0,0 +1,463 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_MATHS_GTEST_MATH_HELPER_H_
|
||||
#define OZZ_OZZ_BASE_MATHS_GTEST_MATH_HELPER_H_
|
||||
|
||||
static const float kFloatNearTolerance = 1e-5f;
|
||||
static const float kFloatNearEstTolerance = 1e-3f;
|
||||
|
||||
// Implements "float near" test as a function. Avoids overloading compiler
|
||||
// optimizer when too much EXPECT_NEAR are used in a single compilation unit.
|
||||
inline void ExpectFloatNear(float _a, float _b,
|
||||
float _tol = kFloatNearTolerance) {
|
||||
EXPECT_NEAR(_a, _b, _tol);
|
||||
}
|
||||
|
||||
// Implements "int equality" test as a function. Avoids overloading compiler
|
||||
// optimizer when too much EXPECT_TRUE are used in a single compilation unit.
|
||||
inline void ExpectIntEq(int _a, int _b) { EXPECT_EQ(_a, _b); }
|
||||
|
||||
// Implements "bool equality" test as a function. Avoids overloading compiler
|
||||
// optimizer when too much EXPECT_TRUE are used in a single compilation unit.
|
||||
inline void ExpectTrue(bool _b) { EXPECT_TRUE(_b); }
|
||||
|
||||
// Macro for testing floats, dedicated to estimated functions with a lower
|
||||
// precision.
|
||||
#define EXPECT_FLOAT_EQ_EST(_expected, _x) \
|
||||
EXPECT_NEAR(_expected, _x, kFloatNearEstTolerance)
|
||||
|
||||
// Macro for testing ozz::math::Float4 members with x, y, z, w float values,
|
||||
// using EXPECT_FLOAT_EQ internally.
|
||||
#define EXPECT_FLOAT4_EQ(_expected, _x, _y, _z, _w) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
const ozz::math::Float4 expected(_expected); \
|
||||
ExpectFloatNear(expected.x, _x); \
|
||||
ExpectFloatNear(expected.y, _y); \
|
||||
ExpectFloatNear(expected.z, _z); \
|
||||
ExpectFloatNear(expected.w, _w); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::Float3 members with x, y, z float values,
|
||||
// using EXPECT_FLOAT_EQ internally.
|
||||
#define EXPECT_FLOAT3_EQ(_expected, _x, _y, _z) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
const ozz::math::Float3 expected(_expected); \
|
||||
ExpectFloatNear(expected.x, _x); \
|
||||
ExpectFloatNear(expected.y, _y); \
|
||||
ExpectFloatNear(expected.z, _z); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::Float2 members with x, y float values,
|
||||
// using EXPECT_NEAR internally.
|
||||
#define EXPECT_FLOAT2_EQ(_expected, _x, _y) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
const ozz::math::Float2 expected(_expected); \
|
||||
ExpectFloatNear(expected.x, _x); \
|
||||
ExpectFloatNear(expected.y, _y); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::Quaternion members with x, y, z, w float value.
|
||||
#define EXPECT_QUATERNION_EQ(_expected, _x, _y, _z, _w) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
const ozz::math::Quaternion expected(_expected); \
|
||||
ExpectFloatNear(expected.x, _x); \
|
||||
ExpectFloatNear(expected.y, _y); \
|
||||
ExpectFloatNear(expected.z, _z); \
|
||||
ExpectFloatNear(expected.w, _w); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
#define _IMPL_EXPECT_SIMDFLOAT_EQ_TOL(_expected, _x, _y, _z, _w, _tol) \
|
||||
\
|
||||
do { \
|
||||
union { \
|
||||
ozz::math::SimdFloat4 ret; \
|
||||
float af[4]; \
|
||||
} u = {_expected}; \
|
||||
ExpectFloatNear(u.af[0], _x, _tol); \
|
||||
ExpectFloatNear(u.af[1], _y, _tol); \
|
||||
ExpectFloatNear(u.af[2], _z, _tol); \
|
||||
ExpectFloatNear(u.af[3], _w, _tol); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
#define _IMPL_EXPECT_SIMDFLOAT_EQ(_expected, _x, _y, _z, _w) \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ_TOL(_expected, _x, _y, _z, _w, kFloatNearTolerance)
|
||||
|
||||
#define _IMPL_EXPECT_SIMDFLOAT_EQ_EST(_expected, _x, _y, _z, _w) \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ_TOL(_expected, _x, _y, _z, _w, \
|
||||
kFloatNearEstTolerance)
|
||||
|
||||
// Macro for testing ozz::math::simd::SimdFloat members with x, y, z, w values.
|
||||
#define EXPECT_SIMDFLOAT_EQ(_expected, _x, _y, _z, _w) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(_expected, _x, _y, _z, _w); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::simd::SimdFloat members with x, y, z, w values.
|
||||
// Dedicated to estimated functions with a lower precision.
|
||||
#define EXPECT_SIMDFLOAT_EQ_EST(_expected, _x, _y, _z, _w) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(_expected, _x, _y, _z, _w); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::simd::SimdFloat members with x, y values with
|
||||
// a user defined precision.
|
||||
#define _IMPL_EXPECT_SIMDFLOAT2_EQ_TOL(_expected, _x, _y, _tol) \
|
||||
\
|
||||
do { \
|
||||
union { \
|
||||
ozz::math::SimdFloat4 ret; \
|
||||
float af[4]; \
|
||||
} u = {_expected}; \
|
||||
ExpectFloatNear(u.af[0], _x, _tol); \
|
||||
ExpectFloatNear(u.af[1], _y, _tol); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::simd::SimdFloat members with x, y values.
|
||||
#define EXPECT_SIMDFLOAT2_EQ(_expected, _x, _y) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
_IMPL_EXPECT_SIMDFLOAT2_EQ_TOL(_expected, _x, _y, kFloatNearTolerance); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::simd::SimdFloat members with x, y values.
|
||||
// Dedicated to estimated functions with a lower precision.
|
||||
#define EXPECT_SIMDFLOAT2_EQ_EST(_expected, _x, _y) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
_IMPL_EXPECT_SIMDFLOAT2_EQ_TOL(_expected, _x, _y, kFloatNearEstTolerance); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::simd::SimdFloat members with x, y, z values.
|
||||
// Dedicated to estimated functions with a user defined precision.
|
||||
#define EXPECT_SIMDFLOAT3_EQ_TOL(_expected, _x, _y, _z, _tol) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
_IMPL_EXPECT_SIMDFLOAT3_EQ_TOL(_expected, _x, _y, _z, _tol); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::simd::SimdFloat members with x, y, z values with
|
||||
// a user defined precision.
|
||||
#define _IMPL_EXPECT_SIMDFLOAT3_EQ_TOL(_expected, _x, _y, _z, _tol) \
|
||||
\
|
||||
do { \
|
||||
union { \
|
||||
ozz::math::SimdFloat4 ret; \
|
||||
float af[4]; \
|
||||
} u = {_expected}; \
|
||||
ExpectFloatNear(u.af[0], _x, _tol); \
|
||||
ExpectFloatNear(u.af[1], _y, _tol); \
|
||||
ExpectFloatNear(u.af[2], _z, _tol); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::simd::SimdFloat members with x, y, z values.
|
||||
#define EXPECT_SIMDFLOAT3_EQ(_expected, _x, _y, _z) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
_IMPL_EXPECT_SIMDFLOAT3_EQ_TOL(_expected, _x, _y, _z, \
|
||||
kFloatNearTolerance); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::simd::SimdFloat members with x, y, z values.
|
||||
// Dedicated to estimated functions with a lower precision.
|
||||
#define EXPECT_SIMDFLOAT3_EQ_EST(_expected, _x, _y, _z) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
_IMPL_EXPECT_SIMDFLOAT3_EQ_TOL(_expected, _x, _y, _z, \
|
||||
kFloatNearEstTolerance); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::simd::SimdFloat members with x, y, z values.
|
||||
// Dedicated to estimated functions with a user defined precision.
|
||||
#define EXPECT_SIMDFLOAT3_EQ_TOL(_expected, _x, _y, _z, _tol) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
_IMPL_EXPECT_SIMDFLOAT3_EQ_TOL(_expected, _x, _y, _z, _tol); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::simd::SimdInt members with x, y, z, w values.
|
||||
#define EXPECT_SIMDINT_EQ(_expected, _x, _y, _z, _w) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
union { \
|
||||
ozz::math::SimdInt4 ret; \
|
||||
int ai[4]; \
|
||||
} u = {_expected}; \
|
||||
ExpectIntEq(u.ai[0], static_cast<int>(_x)); \
|
||||
ExpectIntEq(u.ai[1], static_cast<int>(_y)); \
|
||||
ExpectIntEq(u.ai[2], static_cast<int>(_z)); \
|
||||
ExpectIntEq(u.ai[3], static_cast<int>(_w)); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::SoaFloat4 members with x, y, z, w float values.
|
||||
#define EXPECT_FLOAT4x4_EQ(_expected, _x0, _x1, _x2, _x3, _y0, _y1, _y2, _y3, \
|
||||
_z0, _z1, _z2, _z3, _w0, _w1, _w2, _w3) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
const ozz::math::Float4x4 expected(_expected); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[0], _x0, _x1, _x2, _x3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[1], _y0, _y1, _y2, _y3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[2], _z0, _z1, _z2, _z3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[3], _w0, _w1, _w2, _w3); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::simd::SimdQuaternion members with x, y, z, w
|
||||
// values.
|
||||
#define EXPECT_SIMDQUATERNION_EQ(_expected, _x, _y, _z, _w) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(_expected.xyzw, _x, _y, _z, _w); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::simd::SimdQuaternion members with x, y, z, w
|
||||
// values.
|
||||
#define EXPECT_SIMDQUATERNION_EQ_EST(_expected, _x, _y, _z, _w) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(_expected.xyzw, _x, _y, _z, _w); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::simd::SimdQuaternion members with x, y, z, w
|
||||
// values.
|
||||
#define EXPECT_SIMDQUATERNION_EQ_TOL(_expected, _x, _y, _z, _w, _tol) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ_TOL(_expected.xyzw, _x, _y, _z, _w, _tol); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::SoaFloat4 members with x, y, z, w float values.
|
||||
#define EXPECT_SOAFLOAT4_EQ(_expected, _x0, _x1, _x2, _x3, _y0, _y1, _y2, _y3, \
|
||||
_z0, _z1, _z2, _z3, _w0, _w1, _w2, _w3) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
const ozz::math::SoaFloat4 expected(_expected); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.x, _x0, _x1, _x2, _x3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.y, _y0, _y1, _y2, _y3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.z, _z0, _z1, _z2, _z3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.w, _w0, _w1, _w2, _w3); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::SoaFloat4 members with x, y, z, w float values.
|
||||
// Dedicated to estimated functions with a lower precision.
|
||||
#define EXPECT_SOAFLOAT4_EQ_EST(_expected, _x0, _x1, _x2, _x3, _y0, _y1, _y2, \
|
||||
_y3, _z0, _z1, _z2, _z3, _w0, _w1, _w2, _w3) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
const ozz::math::SoaFloat4 expected(_expected); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.x, _x0, _x1, _x2, _x3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.y, _y0, _y1, _y2, _y3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.z, _z0, _z1, _z2, _z3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.w, _w0, _w1, _w2, _w3); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::SoaFloat3 members with x, y, z float values.
|
||||
#define EXPECT_SOAFLOAT3_EQ(_expected, _x0, _x1, _x2, _x3, _y0, _y1, _y2, _y3, \
|
||||
_z0, _z1, _z2, _z3) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
const ozz::math::SoaFloat3 expected(_expected); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.x, _x0, _x1, _x2, _x3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.y, _y0, _y1, _y2, _y3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.z, _z0, _z1, _z2, _z3); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::SoaFloat3 members with x, y, z float values.
|
||||
// Dedicated to estimated functions with a lower precision.
|
||||
#define EXPECT_SOAFLOAT3_EQ_EST(_expected, _x0, _x1, _x2, _x3, _y0, _y1, _y2, \
|
||||
_y3, _z0, _z1, _z2, _z3) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
const ozz::math::SoaFloat3 expected(_expected); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.x, _x0, _x1, _x2, _x3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.y, _y0, _y1, _y2, _y3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.z, _z0, _z1, _z2, _z3); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::SoaFloat2 members with x, y float values.
|
||||
#define EXPECT_SOAFLOAT2_EQ(_expected, _x0, _x1, _x2, _x3, _y0, _y1, _y2, _y3) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
const ozz::math::SoaFloat2 expected(_expected); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.x, _x0, _x1, _x2, _x3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.y, _y0, _y1, _y2, _y3); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::SoaFloat2 members with x, y float values.
|
||||
// Dedicated to estimated functions with a lower precision.
|
||||
#define EXPECT_SOAFLOAT2_EQ_EST(_expected, _x0, _x1, _x2, _x3, _y0, _y1, _y2, \
|
||||
_y3) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
const ozz::math::SoaFloat2 expected(_expected); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.x, _x0, _x1, _x2, _x3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.y, _y0, _y1, _y2, _y3); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::SoaFloat2 members with x, y float values.
|
||||
#define EXPECT_SOAFLOAT1_EQ(_expected, _x0, _x1, _x2, _x3) \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(_expected, _x0, _x1, _x2, _x3);
|
||||
|
||||
// Macro for testing ozz::math::SoaFloat2 members with x, y float values.
|
||||
// Dedicated to estimated functions with a lower precision.
|
||||
#define EXPECT_SOAFLOAT1_EQ_EST(_expected, _x0, _x1, _x2, _x3) \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(_expected, _x0, _x1, _x2, _x3);
|
||||
|
||||
// Macro for testing ozz::math::SoaQuaternion members with x, y, z, w float
|
||||
// values.
|
||||
#define EXPECT_SOAQUATERNION_EQ(_expected, _x0, _x1, _x2, _x3, _y0, _y1, _y2, \
|
||||
_y3, _z0, _z1, _z2, _z3, _w0, _w1, _w2, _w3) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
const ozz::math::SoaQuaternion expected(_expected); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.x, _x0, _x1, _x2, _x3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.y, _y0, _y1, _y2, _y3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.z, _z0, _z1, _z2, _z3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.w, _w0, _w1, _w2, _w3); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
// Macro for testing ozz::math::SoaQuaternion members with x, y, z, w float
|
||||
// values.
|
||||
// Dedicated to estimated functions with a lower precision.
|
||||
#define EXPECT_SOAQUATERNION_EQ_EST(_expected, _x0, _x1, _x2, _x3, _y0, _y1, \
|
||||
_y2, _y3, _z0, _z1, _z2, _z3, _w0, _w1, \
|
||||
_w2, _w3) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
const ozz::math::SoaQuaternion expected(_expected); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.x, _x0, _x1, _x2, _x3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.y, _y0, _y1, _y2, _y3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.z, _z0, _z1, _z2, _z3); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ_EST(expected.w, _w0, _w1, _w2, _w3); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
|
||||
#define EXPECT_SOAFLOAT4x4_EQ( \
|
||||
_expected, col0xx, col0xy, col0xz, col0xw, col0yx, col0yy, col0yz, col0yw, \
|
||||
col0zx, col0zy, col0zz, col0zw, col0wx, col0wy, col0wz, col0ww, col1xx, \
|
||||
col1xy, col1xz, col1xw, col1yx, col1yy, col1yz, col1yw, col1zx, col1zy, \
|
||||
col1zz, col1zw, col1wx, col1wy, col1wz, col1ww, col2xx, col2xy, col2xz, \
|
||||
col2xw, col2yx, col2yy, col2yz, col2yw, col2zx, col2zy, col2zz, col2zw, \
|
||||
col2wx, col2wy, col2wz, col2ww, col3xx, col3xy, col3xz, col3xw, col3yx, \
|
||||
col3yy, col3yz, col3yw, col3zx, col3zy, col3zz, col3zw, col3wx, col3wy, \
|
||||
col3wz, col3ww) \
|
||||
\
|
||||
do { \
|
||||
SCOPED_TRACE(""); \
|
||||
const ozz::math::SoaFloat4x4 expected(_expected); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[0].x, col0xx, col0xy, col0xz, \
|
||||
col0xw); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[0].y, col0yx, col0yy, col0yz, \
|
||||
col0yw); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[0].z, col0zx, col0zy, col0zz, \
|
||||
col0zw); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[0].w, col0wx, col0wy, col0wz, \
|
||||
col0ww); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[1].x, col1xx, col1xy, col1xz, \
|
||||
col1xw); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[1].y, col1yx, col1yy, col1yz, \
|
||||
col1yw); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[1].z, col1zx, col1zy, col1zz, \
|
||||
col1zw); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[1].w, col1wx, col1wy, col1wz, \
|
||||
col1ww); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[2].x, col2xx, col2xy, col2xz, \
|
||||
col2xw); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[2].y, col2yx, col2yy, col2yz, \
|
||||
col2yw); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[2].z, col2zx, col2zy, col2zz, \
|
||||
col2zw); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[2].w, col2wx, col2wy, col2wz, \
|
||||
col2ww); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[3].x, col3xx, col3xy, col3xz, \
|
||||
col3xw); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[3].y, col3yx, col3yy, col3yz, \
|
||||
col3yw); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[3].z, col3zx, col3zy, col3zz, \
|
||||
col3zw); \
|
||||
_IMPL_EXPECT_SIMDFLOAT_EQ(expected.cols[3].w, col3wx, col3wy, col3wz, \
|
||||
col3ww); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
#endif // OZZ_OZZ_BASE_MATHS_GTEST_MATH_HELPER_H_
|
||||
@@ -0,0 +1,159 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_MATHS_INTERNAL_SIMD_MATH_CONFIG_H_
|
||||
#define OZZ_OZZ_BASE_MATHS_INTERNAL_SIMD_MATH_CONFIG_H_
|
||||
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
// Avoid SIMD instruction detection if reference (aka scalar) implementation is
|
||||
// forced.
|
||||
#if !defined(OZZ_BUILD_SIMD_REF)
|
||||
|
||||
// Try to match a SSE2+ version.
|
||||
#if defined(__AVX2__) || defined(OZZ_SIMD_AVX2)
|
||||
#include <immintrin.h>
|
||||
#define OZZ_SIMD_AVX2
|
||||
#define OZZ_SIMD_AVX // avx is available if avx2 is.
|
||||
#endif
|
||||
|
||||
#if defined(__FMA__) || defined(OZZ_SIMD_FMA)
|
||||
#include <immintrin.h>
|
||||
#define OZZ_SIMD_FMA
|
||||
#endif
|
||||
|
||||
#if defined(__AVX__) || defined(OZZ_SIMD_AVX)
|
||||
#include <immintrin.h>
|
||||
#define OZZ_SIMD_AVX
|
||||
#define OZZ_SIMD_SSE4_2 // SSE4.2 is available if avx is.
|
||||
#endif
|
||||
|
||||
#if defined(__SSE4_2__) || defined(OZZ_SIMD_SSE4_2)
|
||||
#include <nmmintrin.h>
|
||||
#define OZZ_SIMD_SSE4_2
|
||||
#define OZZ_SIMD_SSE4_1 // SSE4.1 is available if SSE4.2 is.
|
||||
#endif
|
||||
|
||||
#if defined(__SSE4_1__) || defined(OZZ_SIMD_SSE4_1)
|
||||
#include <smmintrin.h>
|
||||
#define OZZ_SIMD_SSE4_1
|
||||
#define OZZ_SIMD_SSSE3 // SSSE3 is available if SSE4.1 is.
|
||||
#endif
|
||||
|
||||
#if defined(__SSSE3__) || defined(OZZ_SIMD_SSSE3)
|
||||
#include <tmmintrin.h>
|
||||
#define OZZ_SIMD_SSSE3
|
||||
#define OZZ_SIMD_SSE3 // SSE3 is available if SSSE3 is.
|
||||
#endif
|
||||
|
||||
#if defined(__SSE3__) || defined(OZZ_SIMD_SSE3)
|
||||
#include <pmmintrin.h>
|
||||
#define OZZ_SIMD_SSE3
|
||||
#define OZZ_SIMD_SSE2 // SSE2 is available if SSE3 is.
|
||||
#endif
|
||||
|
||||
// x64/amd64 have SSE2 instructions
|
||||
// _M_IX86_FP is 2 if /arch:SSE2, /arch:AVX or /arch:AVX2 was used.
|
||||
#if defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64) || \
|
||||
(_M_IX86_FP >= 2) || defined(OZZ_SIMD_SSE2)
|
||||
#include <emmintrin.h>
|
||||
#define OZZ_SIMD_SSE2
|
||||
#define OZZ_SIMD_SSEx // OZZ_SIMD_SSEx is the generic flag for SSE support
|
||||
#endif
|
||||
|
||||
// End of SIMD instruction detection
|
||||
#endif // !OZZ_BUILD_SIMD_REF
|
||||
|
||||
// SEE* intrinsics available
|
||||
#if defined(OZZ_SIMD_SSEx)
|
||||
|
||||
namespace ozz {
|
||||
namespace math {
|
||||
|
||||
// Vector of four floating point values.
|
||||
typedef __m128 SimdFloat4;
|
||||
|
||||
// Argument type for Float4.
|
||||
typedef const __m128 _SimdFloat4;
|
||||
|
||||
// Vector of four integer values.
|
||||
typedef __m128i SimdInt4;
|
||||
|
||||
// Argument type for Int4.
|
||||
typedef const __m128i _SimdInt4;
|
||||
} // namespace math
|
||||
} // namespace ozz
|
||||
|
||||
#else // No builtin simd available
|
||||
|
||||
// No simd instruction set detected, switch back to reference implementation.
|
||||
// OZZ_SIMD_REF is the generic flag for SIMD reference implementation.
|
||||
#define OZZ_SIMD_REF
|
||||
|
||||
// Declares reference simd float and integer vectors outside of ozz::math, in
|
||||
// order to match non-reference implementation details.
|
||||
|
||||
// Vector of four floating point values.
|
||||
struct SimdFloat4Def {
|
||||
alignas(16) float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
};
|
||||
|
||||
// Vector of four integer values.
|
||||
struct SimdInt4Def {
|
||||
alignas(16) int x;
|
||||
int y;
|
||||
int z;
|
||||
int w;
|
||||
};
|
||||
|
||||
namespace ozz {
|
||||
namespace math {
|
||||
|
||||
// Vector of four floating point values.
|
||||
typedef SimdFloat4Def SimdFloat4;
|
||||
|
||||
// Argument type for SimdFloat4
|
||||
typedef const SimdFloat4& _SimdFloat4;
|
||||
|
||||
// Vector of four integer values.
|
||||
typedef SimdInt4Def SimdInt4;
|
||||
|
||||
// Argument type for SimdInt4.
|
||||
typedef const SimdInt4& _SimdInt4;
|
||||
|
||||
} // namespace math
|
||||
} // namespace ozz
|
||||
#endif // OZZ_SIMD_x
|
||||
|
||||
// Native SIMD operator already exist on some compilers, so they have to be disable from ozz implementation
|
||||
#if !defined(OZZ_SIMD_REF) && (defined(__GNUC__) || defined(__llvm__))
|
||||
#define OZZ_DISABLE_SSE_NATIVE_OPERATORS
|
||||
#endif
|
||||
#endif // OZZ_OZZ_BASE_MATHS_INTERNAL_SIMD_MATH_CONFIG_H_
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,118 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_MATHS_MATH_ARCHIVE_H_
|
||||
#define OZZ_OZZ_BASE_MATHS_MATH_ARCHIVE_H_
|
||||
|
||||
#include "ozz/base/io/archive_traits.h"
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace math {
|
||||
struct Float2;
|
||||
struct Float3;
|
||||
struct Float4;
|
||||
struct Quaternion;
|
||||
struct Transform;
|
||||
struct Box;
|
||||
struct RectFloat;
|
||||
struct RectInt;
|
||||
} // namespace math
|
||||
namespace io {
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(math::Float2)
|
||||
template <>
|
||||
struct Extern<math::Float2> {
|
||||
static void Save(OArchive& _archive, const math::Float2* _values,
|
||||
size_t _count);
|
||||
static void Load(IArchive& _archive, math::Float2* _values, size_t _count,
|
||||
uint32_t _version);
|
||||
};
|
||||
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(math::Float3)
|
||||
template <>
|
||||
struct Extern<math::Float3> {
|
||||
static void Save(OArchive& _archive, const math::Float3* _values,
|
||||
size_t _count);
|
||||
static void Load(IArchive& _archive, math::Float3* _values, size_t _count,
|
||||
uint32_t _version);
|
||||
};
|
||||
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(math::Float4)
|
||||
template <>
|
||||
struct Extern<math::Float4> {
|
||||
static void Save(OArchive& _archive, const math::Float4* _values,
|
||||
size_t _count);
|
||||
static void Load(IArchive& _archive, math::Float4* _values, size_t _count,
|
||||
uint32_t _version);
|
||||
};
|
||||
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(math::Quaternion)
|
||||
template <>
|
||||
struct Extern<math::Quaternion> {
|
||||
static void Save(OArchive& _archive, const math::Quaternion* _values,
|
||||
size_t _count);
|
||||
static void Load(IArchive& _archive, math::Quaternion* _values, size_t _count,
|
||||
uint32_t _version);
|
||||
};
|
||||
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(math::Transform)
|
||||
template <>
|
||||
struct Extern<math::Transform> {
|
||||
static void Save(OArchive& _archive, const math::Transform* _values,
|
||||
size_t _count);
|
||||
static void Load(IArchive& _archive, math::Transform* _values, size_t _count,
|
||||
uint32_t _version);
|
||||
};
|
||||
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(math::Box)
|
||||
template <>
|
||||
struct Extern<math::Box> {
|
||||
static void Save(OArchive& _archive, const math::Box* _values, size_t _count);
|
||||
static void Load(IArchive& _archive, math::Box* _values, size_t _count,
|
||||
uint32_t _version);
|
||||
};
|
||||
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(math::RectFloat)
|
||||
template <>
|
||||
struct Extern<math::RectFloat> {
|
||||
static void Save(OArchive& _archive, const math::RectFloat* _values,
|
||||
size_t _count);
|
||||
static void Load(IArchive& _archive, math::RectFloat* _values, size_t _count,
|
||||
uint32_t _version);
|
||||
};
|
||||
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(math::RectInt)
|
||||
template <>
|
||||
struct Extern<math::RectInt> {
|
||||
static void Save(OArchive& _archive, const math::RectInt* _values,
|
||||
size_t _count);
|
||||
static void Load(IArchive& _archive, math::RectInt* _values, size_t _count,
|
||||
uint32_t _version);
|
||||
};
|
||||
} // namespace io
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_MATHS_MATH_ARCHIVE_H_
|
||||
@@ -0,0 +1,61 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_MATHS_MATH_CONSTANT_H_
|
||||
#define OZZ_OZZ_BASE_MATHS_MATH_CONSTANT_H_
|
||||
|
||||
#ifndef INCLUDE_OZZ_MATH_CONSTANT_H_
|
||||
#define INCLUDE_OZZ_MATH_CONSTANT_H_
|
||||
|
||||
namespace ozz {
|
||||
namespace math {
|
||||
|
||||
// Defines math trigonometric constants.
|
||||
static const float k2Pi = 6.283185307179586476925286766559f;
|
||||
static const float kPi = 3.1415926535897932384626433832795f;
|
||||
static const float kPi_2 = 1.5707963267948966192313216916398f;
|
||||
static const float kPi_4 = .78539816339744830961566084581988f;
|
||||
static const float kSqrt3 = 1.7320508075688772935274463415059f;
|
||||
static const float kSqrt3_2 = 0.86602540378443864676372317075294f;
|
||||
static const float kSqrt2 = 1.4142135623730950488016887242097f;
|
||||
static const float kSqrt2_2 = 0.70710678118654752440084436210485f;
|
||||
|
||||
// Angle unit conversion constants.
|
||||
static const float kDegreeToRadian = kPi / 180.f;
|
||||
static const float kRadianToDegree = 180.f / kPi;
|
||||
|
||||
// Defines the square normalization tolerance value.
|
||||
static const float kNormalizationToleranceSq = 1e-6f;
|
||||
static const float kNormalizationToleranceEstSq = 2e-3f;
|
||||
|
||||
// Defines the square orthogonalisation tolerance value.
|
||||
static const float kOrthogonalisationToleranceSq = 1e-16f;
|
||||
} // namespace math
|
||||
} // namespace ozz
|
||||
|
||||
#endif // INCLUDE_OZZ_MATH_CONSTANT_H_
|
||||
#endif // OZZ_OZZ_BASE_MATHS_MATH_CONSTANT_H_
|
||||
@@ -0,0 +1,125 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_MATHS_MATH_EX_H_
|
||||
#define OZZ_OZZ_BASE_MATHS_MATH_EX_H_
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace math {
|
||||
|
||||
// Returns the linear interpolation of _a and _b with coefficient _f.
|
||||
// _f is not limited to range [0,1].
|
||||
OZZ_INLINE float Lerp(float _a, float _b, float _f) {
|
||||
return (_b - _a) * _f + _a;
|
||||
}
|
||||
|
||||
// Returns the minimum of _a and _b. Comparison's based on operator <.
|
||||
template <typename _Ty>
|
||||
OZZ_INLINE _Ty Min(_Ty _a, _Ty _b) {
|
||||
return (_a < _b) ? _a : _b;
|
||||
}
|
||||
|
||||
// Returns the maximum of _a and _b. Comparison's based on operator <.
|
||||
template <typename _Ty>
|
||||
OZZ_INLINE _Ty Max(_Ty _a, _Ty _b) {
|
||||
return (_b < _a) ? _a : _b;
|
||||
}
|
||||
|
||||
// Clamps _x between _a and _b. Comparison's based on operator <.
|
||||
// Result is unknown if _a is not less or equal to _b.
|
||||
template <typename _Ty>
|
||||
OZZ_INLINE _Ty Clamp(_Ty _a, _Ty _x, _Ty _b) {
|
||||
const _Ty min = _x < _b ? _x : _b;
|
||||
return min < _a ? _a : min;
|
||||
}
|
||||
|
||||
// Implements int selection, avoiding branching.
|
||||
OZZ_INLINE int Select(bool _b, int _true, int _false) {
|
||||
return _false ^ (-static_cast<int>(_b) & (_true ^ _false));
|
||||
}
|
||||
|
||||
// Implements float selection, avoiding branching.
|
||||
OZZ_INLINE float Select(bool _b, float _true, float _false) {
|
||||
union {
|
||||
float f;
|
||||
int32_t i;
|
||||
} t = {_true};
|
||||
union {
|
||||
float f;
|
||||
int32_t i;
|
||||
} f = {_false};
|
||||
union {
|
||||
int32_t i;
|
||||
float f;
|
||||
} r = {f.i ^ (-static_cast<int32_t>(_b) & (t.i ^ f.i))};
|
||||
return r.f;
|
||||
}
|
||||
|
||||
// Implements pointer selection, avoiding branching.
|
||||
template <typename _Ty>
|
||||
OZZ_INLINE _Ty* Select(bool _b, _Ty* _true, _Ty* _false) {
|
||||
union {
|
||||
_Ty* p;
|
||||
intptr_t i;
|
||||
} t = {_true};
|
||||
union {
|
||||
_Ty* p;
|
||||
intptr_t i;
|
||||
} f = {_false};
|
||||
union {
|
||||
intptr_t i;
|
||||
_Ty* p;
|
||||
} r = {f.i ^ (-static_cast<intptr_t>(_b) & (t.i ^ f.i))};
|
||||
return r.p;
|
||||
}
|
||||
|
||||
// Implements const pointer selection, avoiding branching.
|
||||
template <typename _Ty>
|
||||
OZZ_INLINE const _Ty* Select(bool _b, const _Ty* _true, const _Ty* _false) {
|
||||
union {
|
||||
const _Ty* p;
|
||||
intptr_t i;
|
||||
} t = {_true};
|
||||
union {
|
||||
const _Ty* p;
|
||||
intptr_t i;
|
||||
} f = {_false};
|
||||
union {
|
||||
intptr_t i;
|
||||
const _Ty* p;
|
||||
} r = {f.i ^ (-static_cast<intptr_t>(_b) & (t.i ^ f.i))};
|
||||
return r.p;
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_MATHS_MATH_EX_H_
|
||||
@@ -0,0 +1,370 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_MATHS_QUATERNION_H_
|
||||
#define OZZ_OZZ_BASE_MATHS_QUATERNION_H_
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "ozz/base/maths/math_constant.h"
|
||||
#include "ozz/base/maths/math_ex.h"
|
||||
#include "ozz/base/maths/vec_float.h"
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace math {
|
||||
|
||||
struct Quaternion {
|
||||
float x, y, z, w;
|
||||
|
||||
// Constructs an uninitialized quaternion.
|
||||
OZZ_INLINE Quaternion() {}
|
||||
|
||||
// Constructs a quaternion from 4 floating point values.
|
||||
OZZ_INLINE Quaternion(float _x, float _y, float _z, float _w)
|
||||
: x(_x), y(_y), z(_z), w(_w) {}
|
||||
|
||||
// Returns a normalized quaternion initialized from an axis angle
|
||||
// representation.
|
||||
// Assumes the axis part (x, y, z) of _axis_angle is normalized.
|
||||
// _angle.x is the angle in radian.
|
||||
static OZZ_INLINE Quaternion FromAxisAngle(const Float3& _axis, float _angle);
|
||||
|
||||
// Returns a normalized quaternion initialized from an axis and angle cosine
|
||||
// representation.
|
||||
// Assumes the axis part (x, y, z) of _axis_angle is normalized.
|
||||
// _angle.x is the angle cosine in radian, it must be within [-1,1] range.
|
||||
static OZZ_INLINE Quaternion FromAxisCosAngle(const Float3& _axis,
|
||||
float _cos);
|
||||
|
||||
// Returns a normalized quaternion initialized from an Euler representation.
|
||||
// Euler angles are ordered Heading, Elevation and Bank, or Yaw, Pitch and
|
||||
// Roll.
|
||||
static OZZ_INLINE Quaternion FromEuler(float _yaw, float _pitch,
|
||||
float _roll);
|
||||
|
||||
// Returns the quaternion that will rotate vector _from into vector _to,
|
||||
// around their plan perpendicular axis.The input vectors don't need to be
|
||||
// normalized, they can be null as well.
|
||||
static OZZ_INLINE Quaternion FromVectors(const Float3& _from,
|
||||
const Float3& _to);
|
||||
|
||||
// Returns the quaternion that will rotate vector _from into vector _to,
|
||||
// around their plan perpendicular axis. The input vectors must be normalized.
|
||||
static OZZ_INLINE Quaternion FromUnitVectors(const Float3& _from,
|
||||
const Float3& _to);
|
||||
|
||||
// Returns the identity quaternion.
|
||||
static OZZ_INLINE Quaternion identity() {
|
||||
return Quaternion(0.f, 0.f, 0.f, 1.f);
|
||||
}
|
||||
};
|
||||
|
||||
// Returns true if each element of a is equal to each element of _b.
|
||||
OZZ_INLINE bool operator==(const Quaternion& _a, const Quaternion& _b) {
|
||||
return _a.x == _b.x && _a.y == _b.y && _a.z == _b.z && _a.w == _b.w;
|
||||
}
|
||||
|
||||
// Returns true if one element of a differs from one element of _b.
|
||||
OZZ_INLINE bool operator!=(const Quaternion& _a, const Quaternion& _b) {
|
||||
return _a.x != _b.x || _a.y != _b.y || _a.z != _b.z || _a.w != _b.w;
|
||||
}
|
||||
|
||||
// Returns the conjugate of _q. This is the same as the inverse if _q is
|
||||
// normalized. Otherwise the magnitude of the inverse is 1.f/|_q|.
|
||||
OZZ_INLINE Quaternion Conjugate(const Quaternion& _q) {
|
||||
return Quaternion(-_q.x, -_q.y, -_q.z, _q.w);
|
||||
}
|
||||
|
||||
// Returns the addition of _a and _b.
|
||||
OZZ_INLINE Quaternion operator+(const Quaternion& _a, const Quaternion& _b) {
|
||||
return Quaternion(_a.x + _b.x, _a.y + _b.y, _a.z + _b.z, _a.w + _b.w);
|
||||
}
|
||||
|
||||
// Returns the multiplication of _q and a scalar _f.
|
||||
OZZ_INLINE Quaternion operator*(const Quaternion& _q, float _f) {
|
||||
return Quaternion(_q.x * _f, _q.y * _f, _q.z * _f, _q.w * _f);
|
||||
}
|
||||
|
||||
// Returns the multiplication of _a and _b. If both _a and _b are normalized,
|
||||
// then the result is normalized.
|
||||
OZZ_INLINE Quaternion operator*(const Quaternion& _a, const Quaternion& _b) {
|
||||
return Quaternion(_a.w * _b.x + _a.x * _b.w + _a.y * _b.z - _a.z * _b.y,
|
||||
_a.w * _b.y + _a.y * _b.w + _a.z * _b.x - _a.x * _b.z,
|
||||
_a.w * _b.z + _a.z * _b.w + _a.x * _b.y - _a.y * _b.x,
|
||||
_a.w * _b.w - _a.x * _b.x - _a.y * _b.y - _a.z * _b.z);
|
||||
}
|
||||
|
||||
// Returns the negate of _q. This represent the same rotation as q.
|
||||
OZZ_INLINE Quaternion operator-(const Quaternion& _q) {
|
||||
return Quaternion(-_q.x, -_q.y, -_q.z, -_q.w);
|
||||
}
|
||||
|
||||
// Returns true if the angle between _a and _b is less than _tolerance.
|
||||
OZZ_INLINE bool Compare(const math::Quaternion& _a, const math::Quaternion& _b,
|
||||
float _cos_half_tolerance) {
|
||||
// Computes w component of a-1 * b.
|
||||
const float cos_half_angle =
|
||||
_a.x * _b.x + _a.y * _b.y + _a.z * _b.z + _a.w * _b.w;
|
||||
return std::abs(cos_half_angle) >= _cos_half_tolerance;
|
||||
}
|
||||
|
||||
// Returns true if _q is a normalized quaternion.
|
||||
OZZ_INLINE bool IsNormalized(const Quaternion& _q) {
|
||||
const float sq_len = _q.x * _q.x + _q.y * _q.y + _q.z * _q.z + _q.w * _q.w;
|
||||
return std::abs(sq_len - 1.f) < kNormalizationToleranceSq;
|
||||
}
|
||||
|
||||
// Returns the normalized quaternion _q.
|
||||
OZZ_INLINE Quaternion Normalize(const Quaternion& _q) {
|
||||
const float sq_len = _q.x * _q.x + _q.y * _q.y + _q.z * _q.z + _q.w * _q.w;
|
||||
assert(sq_len != 0.f && "_q is not normalizable");
|
||||
const float inv_len = 1.f / std::sqrt(sq_len);
|
||||
return Quaternion(_q.x * inv_len, _q.y * inv_len, _q.z * inv_len,
|
||||
_q.w * inv_len);
|
||||
}
|
||||
|
||||
// Returns the normalized quaternion _q if the norm of _q is not 0.
|
||||
// Otherwise returns _safer.
|
||||
OZZ_INLINE Quaternion NormalizeSafe(const Quaternion& _q,
|
||||
const Quaternion& _safer) {
|
||||
assert(IsNormalized(_safer) && "_safer is not normalized");
|
||||
const float sq_len = _q.x * _q.x + _q.y * _q.y + _q.z * _q.z + _q.w * _q.w;
|
||||
if (sq_len == 0) {
|
||||
return _safer;
|
||||
}
|
||||
const float inv_len = 1.f / std::sqrt(sq_len);
|
||||
return Quaternion(_q.x * inv_len, _q.y * inv_len, _q.z * inv_len,
|
||||
_q.w * inv_len);
|
||||
}
|
||||
|
||||
OZZ_INLINE Quaternion Quaternion::FromAxisAngle(const Float3& _axis,
|
||||
float _angle) {
|
||||
assert(IsNormalized(_axis) && "axis is not normalized.");
|
||||
const float half_angle = _angle * .5f;
|
||||
const float half_sin = std::sin(half_angle);
|
||||
const float half_cos = std::cos(half_angle);
|
||||
return Quaternion(_axis.x * half_sin, _axis.y * half_sin, _axis.z * half_sin,
|
||||
half_cos);
|
||||
}
|
||||
|
||||
OZZ_INLINE Quaternion Quaternion::FromAxisCosAngle(const Float3& _axis,
|
||||
float _cos) {
|
||||
assert(IsNormalized(_axis) && "axis is not normalized.");
|
||||
assert(_cos >= -1.f && _cos <= 1.f && "cos is not in [-1,1] range.");
|
||||
|
||||
const float half_cos2 = (1.f + _cos) * 0.5f;
|
||||
const float half_sin = std::sqrt(1.f - half_cos2);
|
||||
return Quaternion(_axis.x * half_sin, _axis.y * half_sin, _axis.z * half_sin,
|
||||
std::sqrt(half_cos2));
|
||||
}
|
||||
|
||||
// Returns to an axis angle representation of quaternion _q.
|
||||
// Assumes quaternion _q is normalized.
|
||||
OZZ_INLINE Float4 ToAxisAngle(const Quaternion& _q) {
|
||||
assert(IsNormalized(_q));
|
||||
const float clamped_w = Clamp(-1.f, _q.w, 1.f);
|
||||
const float angle = 2.f * std::acos(clamped_w);
|
||||
const float s = std::sqrt(1.f - clamped_w * clamped_w);
|
||||
|
||||
// Assuming quaternion normalized then s always positive.
|
||||
if (s < .001f) { // Tests to avoid divide by zero.
|
||||
// If s close to zero then direction of axis is not important.
|
||||
return Float4(1.f, 0.f, 0.f, angle);
|
||||
} else {
|
||||
// Normalize axis
|
||||
const float inv_s = 1.f / s;
|
||||
return Float4(_q.x * inv_s, _q.y * inv_s, _q.z * inv_s, angle);
|
||||
}
|
||||
}
|
||||
|
||||
OZZ_INLINE Quaternion Quaternion::FromEuler(float _yaw, float _pitch,
|
||||
float _roll) {
|
||||
const float half_yaw = _yaw * .5f;
|
||||
const float c1 = std::cos(half_yaw);
|
||||
const float s1 = std::sin(half_yaw);
|
||||
const float half_pitch = _pitch * .5f;
|
||||
const float c2 = std::cos(half_pitch);
|
||||
const float s2 = std::sin(half_pitch);
|
||||
const float half_roll = _roll * .5f;
|
||||
const float c3 = std::cos(half_roll);
|
||||
const float s3 = std::sin(half_roll);
|
||||
const float c1c2 = c1 * c2;
|
||||
const float s1s2 = s1 * s2;
|
||||
return Quaternion(c1c2 * s3 + s1s2 * c3, s1 * c2 * c3 + c1 * s2 * s3,
|
||||
c1 * s2 * c3 - s1 * c2 * s3, c1c2 * c3 - s1s2 * s3);
|
||||
}
|
||||
|
||||
// Returns to an Euler representation of quaternion _q.
|
||||
// Quaternion _q does not require to be normalized.
|
||||
OZZ_INLINE Float3 ToEuler(const Quaternion& _q) {
|
||||
const float sqw = _q.w * _q.w;
|
||||
const float sqx = _q.x * _q.x;
|
||||
const float sqy = _q.y * _q.y;
|
||||
const float sqz = _q.z * _q.z;
|
||||
// If normalized is one, otherwise is correction factor.
|
||||
const float unit = sqx + sqy + sqz + sqw;
|
||||
const float test = _q.x * _q.y + _q.z * _q.w;
|
||||
Float3 euler;
|
||||
if (test > .499f * unit) { // Singularity at north pole
|
||||
euler.x = 2.f * std::atan2(_q.x, _q.w);
|
||||
euler.y = ozz::math::kPi_2;
|
||||
euler.z = 0;
|
||||
} else if (test < -.499f * unit) { // Singularity at south pole
|
||||
euler.x = -2 * std::atan2(_q.x, _q.w);
|
||||
euler.y = -kPi_2;
|
||||
euler.z = 0;
|
||||
} else {
|
||||
euler.x = std::atan2(2.f * _q.y * _q.w - 2.f * _q.x * _q.z,
|
||||
sqx - sqy - sqz + sqw);
|
||||
euler.y = std::asin(2.f * test / unit);
|
||||
euler.z = std::atan2(2.f * _q.x * _q.w - 2.f * _q.y * _q.z,
|
||||
-sqx + sqy - sqz + sqw);
|
||||
}
|
||||
return euler;
|
||||
}
|
||||
|
||||
OZZ_INLINE Quaternion Quaternion::FromVectors(const Float3& _from,
|
||||
const Float3& _to) {
|
||||
// http://lolengine.net/blog/2014/02/24/quaternion-from-two-vectors-final
|
||||
|
||||
const float norm_from_norm_to = std::sqrt(LengthSqr(_from) * LengthSqr(_to));
|
||||
if (norm_from_norm_to < 1.e-5f) {
|
||||
return Quaternion::identity();
|
||||
}
|
||||
const float real_part = norm_from_norm_to + Dot(_from, _to);
|
||||
Quaternion quat;
|
||||
if (real_part < 1.e-6f * norm_from_norm_to) {
|
||||
// If _from and _to are exactly opposite, rotate 180 degrees around an
|
||||
// arbitrary orthogonal axis. Axis normalization can happen later, when we
|
||||
// normalize the quaternion.
|
||||
quat = std::abs(_from.x) > std::abs(_from.z)
|
||||
? Quaternion(-_from.y, _from.x, 0.f, 0.f)
|
||||
: Quaternion(0.f, -_from.z, _from.y, 0.f);
|
||||
} else {
|
||||
const Float3 cross = Cross(_from, _to);
|
||||
quat = Quaternion(cross.x, cross.y, cross.z, real_part);
|
||||
}
|
||||
return Normalize(quat);
|
||||
}
|
||||
|
||||
OZZ_INLINE Quaternion Quaternion::FromUnitVectors(const Float3& _from,
|
||||
const Float3& _to) {
|
||||
assert(IsNormalized(_from) && IsNormalized(_to) &&
|
||||
"Input vectors must be normalized.");
|
||||
|
||||
// http://lolengine.net/blog/2014/02/24/quaternion-from-two-vectors-final
|
||||
const float real_part = 1.f + Dot(_from, _to);
|
||||
if (real_part < 1.e-6f) {
|
||||
// If _from and _to are exactly opposite, rotate 180 degrees around an
|
||||
// arbitrary orthogonal axis.
|
||||
// Normalisation isn't needed, as from is already.
|
||||
return std::abs(_from.x) > std::abs(_from.z)
|
||||
? Quaternion(-_from.y, _from.x, 0.f, 0.f)
|
||||
: Quaternion(0.f, -_from.z, _from.y, 0.f);
|
||||
} else {
|
||||
const Float3 cross = Cross(_from, _to);
|
||||
return Normalize(Quaternion(cross.x, cross.y, cross.z, real_part));
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the dot product of _a and _b.
|
||||
OZZ_INLINE float Dot(const Quaternion& _a, const Quaternion& _b) {
|
||||
return _a.x * _b.x + _a.y * _b.y + _a.z * _b.z + _a.w * _b.w;
|
||||
}
|
||||
|
||||
// Returns the linear interpolation of quaternion _a and _b with coefficient
|
||||
// _f.
|
||||
OZZ_INLINE Quaternion Lerp(const Quaternion& _a, const Quaternion& _b,
|
||||
float _f) {
|
||||
return Quaternion((_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
|
||||
(_b.z - _a.z) * _f + _a.z, (_b.w - _a.w) * _f + _a.w);
|
||||
}
|
||||
|
||||
// Returns the linear interpolation of quaternion _a and _b with coefficient
|
||||
// _f. _a and _n must be from the same hemisphere (aka dot(_a, _b) >= 0).
|
||||
OZZ_INLINE Quaternion NLerp(const Quaternion& _a, const Quaternion& _b,
|
||||
float _f) {
|
||||
const Float4 lerp((_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
|
||||
(_b.z - _a.z) * _f + _a.z, (_b.w - _a.w) * _f + _a.w);
|
||||
const float sq_len =
|
||||
lerp.x * lerp.x + lerp.y * lerp.y + lerp.z * lerp.z + lerp.w * lerp.w;
|
||||
const float inv_len = 1.f / std::sqrt(sq_len);
|
||||
return Quaternion(lerp.x * inv_len, lerp.y * inv_len, lerp.z * inv_len,
|
||||
lerp.w * inv_len);
|
||||
}
|
||||
|
||||
// Returns the spherical interpolation of quaternion _a and _b with
|
||||
// coefficient _f.
|
||||
OZZ_INLINE Quaternion SLerp(const Quaternion& _a, const Quaternion& _b,
|
||||
float _f) {
|
||||
assert(IsNormalized(_a));
|
||||
assert(IsNormalized(_b));
|
||||
// Calculate angle between them.
|
||||
float cos_half_theta = _a.x * _b.x + _a.y * _b.y + _a.z * _b.z + _a.w * _b.w;
|
||||
|
||||
// If _a=_b or _a=-_b then theta = 0 and we can return _a.
|
||||
if (std::abs(cos_half_theta) >= .999f) {
|
||||
return _a;
|
||||
}
|
||||
|
||||
// Calculate temporary values.
|
||||
const float half_theta = std::acos(cos_half_theta);
|
||||
const float sin_half_theta = std::sqrt(1.f - cos_half_theta * cos_half_theta);
|
||||
|
||||
// If theta = pi then result is not fully defined, we could rotate around
|
||||
// any axis normal to _a or _b.
|
||||
if (sin_half_theta < .001f) {
|
||||
return Quaternion((_a.x + _b.x) * .5f, (_a.y + _b.y) * .5f,
|
||||
(_a.z + _b.z) * .5f, (_a.w + _b.w) * .5f);
|
||||
}
|
||||
|
||||
const float ratio_a = std::sin((1.f - _f) * half_theta) / sin_half_theta;
|
||||
const float ratio_b = std::sin(_f * half_theta) / sin_half_theta;
|
||||
|
||||
// Calculate Quaternion.
|
||||
return Quaternion(
|
||||
ratio_a * _a.x + ratio_b * _b.x, ratio_a * _a.y + ratio_b * _b.y,
|
||||
ratio_a * _a.z + ratio_b * _b.z, ratio_a * _a.w + ratio_b * _b.w);
|
||||
}
|
||||
|
||||
// Computes the transformation of a Quaternion and a vector _v.
|
||||
// This is equivalent to carrying out the quaternion multiplications:
|
||||
// _q.conjugate() * (*this) * _q
|
||||
OZZ_INLINE Float3 TransformVector(const Quaternion& _q, const Float3& _v) {
|
||||
// http://www.neil.dantam.name/note/dantam-quaternion.pdf
|
||||
// _v + 2.f * cross(_q.xyz, cross(_q.xyz, _v) + _q.w * _v);
|
||||
const Float3 a(_q.y * _v.z - _q.z * _v.y + _v.x * _q.w,
|
||||
_q.z * _v.x - _q.x * _v.z + _v.y * _q.w,
|
||||
_q.x * _v.y - _q.y * _v.x + _v.z * _q.w);
|
||||
const Float3 b(_q.y * a.z - _q.z * a.y, _q.z * a.x - _q.x * a.z,
|
||||
_q.x * a.y - _q.y * a.x);
|
||||
return Float3(_v.x + b.x + b.x, _v.y + b.y + b.y, _v.z + b.z + b.z);
|
||||
}
|
||||
} // namespace math
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_MATHS_QUATERNION_H_
|
||||
@@ -0,0 +1,99 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_MATHS_RECT_H_
|
||||
#define OZZ_OZZ_BASE_MATHS_RECT_H_
|
||||
|
||||
namespace ozz {
|
||||
namespace math {
|
||||
|
||||
// Defines a rectangle by the integer coordinates of its lower-left and
|
||||
// width-height.
|
||||
struct RectInt {
|
||||
// Constructs a uninitialized rectangle.
|
||||
RectInt() {}
|
||||
|
||||
// Constructs a rectangle with the specified arguments.
|
||||
RectInt(int _left, int _bottom, int _width, int _height)
|
||||
: left(_left), bottom(_bottom), width(_width), height(_height) {}
|
||||
|
||||
// Tests whether _x and _y coordinates are within rectangle bounds.
|
||||
bool is_inside(int _x, int _y) const {
|
||||
return _x >= left && _x < left + width && _y >= bottom &&
|
||||
_y < bottom + height;
|
||||
}
|
||||
|
||||
// Gets the rectangle x coordinate of the right rectangle side.
|
||||
int right() const { return left + width; }
|
||||
|
||||
// Gets the rectangle y coordinate of the top rectangle side.
|
||||
int top() const { return bottom + height; }
|
||||
|
||||
// Specifies the x-coordinate of the lower side.
|
||||
int left;
|
||||
// Specifies the x-coordinate of the left side.
|
||||
int bottom;
|
||||
// Specifies the width of the rectangle.
|
||||
int width;
|
||||
// Specifies the height of the rectangle..
|
||||
int height;
|
||||
};
|
||||
|
||||
// Defines a rectangle by the floating point coordinates of its lower-left
|
||||
// and width-height.
|
||||
struct RectFloat {
|
||||
// Constructs a uninitialized rectangle.
|
||||
RectFloat() {}
|
||||
|
||||
// Constructs a rectangle with the specified arguments.
|
||||
RectFloat(float _left, float _bottom, float _width, float _height)
|
||||
: left(_left), bottom(_bottom), width(_width), height(_height) {}
|
||||
|
||||
// Tests whether _x and _y coordinates are within rectangle bounds
|
||||
bool is_inside(float _x, float _y) const {
|
||||
return _x >= left && _x < left + width && _y >= bottom &&
|
||||
_y < bottom + height;
|
||||
}
|
||||
|
||||
// Gets the rectangle x coordinate of the right rectangle side.
|
||||
float right() const { return left + width; }
|
||||
|
||||
// Gets the rectangle y coordinate of the top rectangle side.
|
||||
float top() const { return bottom + height; }
|
||||
|
||||
// Specifies the x-coordinate of the lower side.
|
||||
float left;
|
||||
// Specifies the x-coordinate of the left side.
|
||||
float bottom;
|
||||
// Specifies the width of the rectangle.
|
||||
float width;
|
||||
// Specifies the height of the rectangle.
|
||||
float height;
|
||||
};
|
||||
} // namespace math
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_MATHS_RECT_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,65 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_MATHS_SIMD_MATH_ARCHIVE_H_
|
||||
#define OZZ_OZZ_BASE_MATHS_SIMD_MATH_ARCHIVE_H_
|
||||
|
||||
#include "ozz/base/io/archive_traits.h"
|
||||
#include "ozz/base/maths/simd_math.h"
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace io {
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(math::SimdFloat4)
|
||||
template <>
|
||||
struct Extern<math::SimdFloat4> {
|
||||
static void Save(OArchive& _archive, const math::SimdFloat4* _values,
|
||||
size_t _count);
|
||||
static void Load(IArchive& _archive, math::SimdFloat4* _values, size_t _count,
|
||||
uint32_t _version);
|
||||
};
|
||||
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(math::SimdInt4)
|
||||
template <>
|
||||
struct Extern<math::SimdInt4> {
|
||||
static void Save(OArchive& _archive, const math::SimdInt4* _values,
|
||||
size_t _count);
|
||||
static void Load(IArchive& _archive, math::SimdInt4* _values, size_t _count,
|
||||
uint32_t _version);
|
||||
};
|
||||
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(math::Float4x4)
|
||||
template <>
|
||||
struct Extern<math::Float4x4> {
|
||||
static void Save(OArchive& _archive, const math::Float4x4* _values,
|
||||
size_t _count);
|
||||
static void Load(IArchive& _archive, math::Float4x4* _values, size_t _count,
|
||||
uint32_t _version);
|
||||
};
|
||||
} // namespace io
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_MATHS_SIMD_MATH_ARCHIVE_H_
|
||||
@@ -0,0 +1,274 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_MATHS_SIMD_QUATERNION_H_
|
||||
#define OZZ_OZZ_BASE_MATHS_SIMD_QUATERNION_H_
|
||||
|
||||
#include "ozz/base/maths/simd_math.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
// Implement simd quaternion.
|
||||
namespace ozz {
|
||||
namespace math {
|
||||
// Declare the Quaternion type.
|
||||
struct SimdQuaternion {
|
||||
SimdFloat4 xyzw;
|
||||
|
||||
// Returns the identity quaternion.
|
||||
static OZZ_INLINE SimdQuaternion identity() {
|
||||
const SimdQuaternion quat = {simd_float4::w_axis()};
|
||||
return quat;
|
||||
}
|
||||
|
||||
// the angle in radian.
|
||||
static OZZ_INLINE SimdQuaternion FromAxisAngle(_SimdFloat4 _axis,
|
||||
_SimdFloat4 _angle);
|
||||
|
||||
// Returns a normalized quaternion initialized from an axis and angle cosine
|
||||
// representation.
|
||||
// Assumes the axis part (x, y, z) of _axis_angle is normalized.
|
||||
// _angle.x is the angle cosine in radian, it must be within [-1,1] range.
|
||||
static OZZ_INLINE SimdQuaternion FromAxisCosAngle(_SimdFloat4 _axis,
|
||||
_SimdFloat4 _cos);
|
||||
|
||||
// Returns the quaternion that will rotate vector _from into vector _to,
|
||||
// around their plan perpendicular axis.The input vectors don't need to be
|
||||
// normalized, they can be null also.
|
||||
static OZZ_INLINE SimdQuaternion FromVectors(_SimdFloat4 _from,
|
||||
_SimdFloat4 _to);
|
||||
|
||||
// Returns the quaternion that will rotate vector _from into vector _to,
|
||||
// around their plan perpendicular axis. The input vectors must be normalized.
|
||||
static OZZ_INLINE SimdQuaternion FromUnitVectors(_SimdFloat4 _from,
|
||||
_SimdFloat4 _to);
|
||||
|
||||
// Returns a normalized quaternion initialized from an axis angle
|
||||
// representation.
|
||||
// Assumes the axis part (x, y, z) of _axis_angle is normalized. _angle.x is
|
||||
};
|
||||
|
||||
// Returns the multiplication of _a and _b. If both _a and _b are normalized,
|
||||
// then the result is normalized.
|
||||
OZZ_INLINE SimdQuaternion operator*(const SimdQuaternion& _a,
|
||||
const SimdQuaternion& _b) {
|
||||
// Original quaternion multiplication can be swizzled in a simd friendly way
|
||||
// if w is negated, and some w multiplications parts (1st/last) are swaped.
|
||||
//
|
||||
// p1 p2 p3 p4
|
||||
// _a.w * _b.x + _a.x * _b.w + _a.y * _b.z - _a.z * _b.y
|
||||
// _a.w * _b.y + _a.y * _b.w + _a.z * _b.x - _a.x * _b.z
|
||||
// _a.w * _b.z + _a.z * _b.w + _a.x * _b.y - _a.y * _b.x
|
||||
// _a.w * _b.w - _a.x * _b.x - _a.y * _b.y - _a.z * _b.z
|
||||
// ... becomes ->
|
||||
// _a.w * _b.x + _a.x * _b.w + _a.y * _b.z - _a.z * _b.y
|
||||
// _a.w * _b.y + _a.y * _b.w + _a.z * _b.x - _a.x * _b.z
|
||||
// _a.w * _b.z + _a.z * _b.w + _a.x * _b.y - _a.y * _b.x
|
||||
// - (_a.z * _b.z + _a.x * _b.x + _a.y * _b.y - _a.w * _b.w)
|
||||
const SimdFloat4 p1 =
|
||||
Swizzle<3, 3, 3, 2>(_a.xyzw) * Swizzle<0, 1, 2, 2>(_b.xyzw);
|
||||
const SimdFloat4 p2 =
|
||||
Swizzle<0, 1, 2, 0>(_a.xyzw) * Swizzle<3, 3, 3, 0>(_b.xyzw);
|
||||
const SimdFloat4 p13 =
|
||||
MAdd(Swizzle<1, 2, 0, 1>(_a.xyzw), Swizzle<2, 0, 1, 1>(_b.xyzw), p1);
|
||||
const SimdFloat4 p24 =
|
||||
NMAdd(Swizzle<2, 0, 1, 3>(_a.xyzw), Swizzle<1, 2, 0, 3>(_b.xyzw), p2);
|
||||
const SimdQuaternion quat = {Xor(p13 + p24, simd_int4::mask_sign_w())};
|
||||
return quat;
|
||||
}
|
||||
|
||||
// Returns the conjugate of _q. This is the same as the inverse if _q is
|
||||
// normalized. Otherwise the magnitude of the inverse is 1.f/|_q|.
|
||||
OZZ_INLINE SimdQuaternion Conjugate(const SimdQuaternion& _q) {
|
||||
const SimdQuaternion quat = {Xor(_q.xyzw, simd_int4::mask_sign_xyz())};
|
||||
return quat;
|
||||
}
|
||||
|
||||
// Returns the negate of _q. This represent the same rotation as q.
|
||||
OZZ_INLINE SimdQuaternion operator-(const SimdQuaternion& _q) {
|
||||
const SimdQuaternion quat = {Xor(_q.xyzw, simd_int4::mask_sign())};
|
||||
return quat;
|
||||
}
|
||||
|
||||
// Returns the normalized quaternion _q.
|
||||
OZZ_INLINE SimdQuaternion Normalize(const SimdQuaternion& _q) {
|
||||
const SimdQuaternion quat = {Normalize4(_q.xyzw)};
|
||||
return quat;
|
||||
}
|
||||
|
||||
// Returns the normalized quaternion _q if the norm of _q is not 0.
|
||||
// Otherwise returns _safer.
|
||||
OZZ_INLINE SimdQuaternion NormalizeSafe(const SimdQuaternion& _q,
|
||||
const SimdQuaternion& _safer) {
|
||||
const SimdQuaternion quat = {NormalizeSafe4(_q.xyzw, _safer.xyzw)};
|
||||
return quat;
|
||||
}
|
||||
|
||||
// Returns the estimated normalized quaternion _q.
|
||||
OZZ_INLINE SimdQuaternion NormalizeEst(const SimdQuaternion& _q) {
|
||||
const SimdQuaternion quat = {NormalizeEst4(_q.xyzw)};
|
||||
return quat;
|
||||
}
|
||||
|
||||
// Returns the estimated normalized quaternion _q if the norm of _q is not 0.
|
||||
// Otherwise returns _safer.
|
||||
OZZ_INLINE SimdQuaternion NormalizeSafeEst(const SimdQuaternion& _q,
|
||||
const SimdQuaternion& _safer) {
|
||||
const SimdQuaternion quat = {NormalizeSafeEst4(_q.xyzw, _safer.xyzw)};
|
||||
return quat;
|
||||
}
|
||||
|
||||
// Tests if the _q is a normalized quaternion.
|
||||
// Returns the result in the x component of the returned vector. y, z and w are
|
||||
// set to 0.
|
||||
OZZ_INLINE SimdInt4 IsNormalized(const SimdQuaternion& _q) {
|
||||
return IsNormalized4(_q.xyzw);
|
||||
}
|
||||
|
||||
// Tests if the _q is a normalized quaternion.
|
||||
// Uses the estimated normalization coefficient, that matches estimated math
|
||||
// functions (RecpEst, MormalizeEst...).
|
||||
// Returns the result in the x component of the returned vector. y, z and w are
|
||||
// set to 0.
|
||||
OZZ_INLINE SimdInt4 IsNormalizedEst(const SimdQuaternion& _q) {
|
||||
return IsNormalizedEst4(_q.xyzw);
|
||||
}
|
||||
|
||||
OZZ_INLINE SimdQuaternion SimdQuaternion::FromAxisAngle(_SimdFloat4 _axis,
|
||||
_SimdFloat4 _angle) {
|
||||
assert(AreAllTrue1(IsNormalizedEst3(_axis)) && "axis is not normalized.");
|
||||
const SimdFloat4 half_angle = _angle * simd_float4::Load1(.5f);
|
||||
const SimdFloat4 half_sin = SinX(half_angle);
|
||||
const SimdFloat4 half_cos = CosX(half_angle);
|
||||
const SimdQuaternion quat = {SetW(_axis * SplatX(half_sin), half_cos)};
|
||||
return quat;
|
||||
}
|
||||
|
||||
OZZ_INLINE SimdQuaternion SimdQuaternion::FromAxisCosAngle(_SimdFloat4 _axis,
|
||||
_SimdFloat4 _cos) {
|
||||
const SimdFloat4 one = simd_float4::one();
|
||||
const SimdFloat4 half = simd_float4::Load1(.5f);
|
||||
|
||||
assert(AreAllTrue1(IsNormalizedEst3(_axis)) && "axis is not normalized.");
|
||||
assert(AreAllTrue1(And(CmpGe(_cos, -one), CmpLe(_cos, one))) &&
|
||||
"cos is not in [-1,1] range.");
|
||||
|
||||
const SimdFloat4 half_cos2 = (one + _cos) * half;
|
||||
const SimdFloat4 half_sin2 = one - half_cos2;
|
||||
const SimdFloat4 half_sincos2 = SetY(half_cos2, half_sin2);
|
||||
const SimdFloat4 half_sincos = Sqrt(half_sincos2);
|
||||
const SimdFloat4 half_sin = SplatY(half_sincos);
|
||||
const SimdQuaternion quat = {SetW(_axis * half_sin, half_sincos)};
|
||||
return quat;
|
||||
}
|
||||
|
||||
// Returns to an axis angle representation of quaternion _q.
|
||||
// Assumes quaternion _q is normalized.
|
||||
OZZ_INLINE SimdFloat4 ToAxisAngle(const SimdQuaternion& _q) {
|
||||
assert(AreAllTrue1(IsNormalizedEst4(_q.xyzw)) && "_q is not normalized.");
|
||||
const SimdFloat4 x_axis = simd_float4::x_axis();
|
||||
const SimdFloat4 clamped_w = Clamp(-x_axis, SplatW(_q.xyzw), x_axis);
|
||||
const SimdFloat4 half_angle = ACosX(clamped_w);
|
||||
|
||||
// Assuming quaternion is normalized then s always positive.
|
||||
const SimdFloat4 s = SplatX(SqrtX(NMAdd(clamped_w, clamped_w, x_axis)));
|
||||
// If s is close to zero then direction of axis is not important.
|
||||
const SimdInt4 low = CmpLt(s, simd_float4::Load1(1e-3f));
|
||||
return Select(low, x_axis,
|
||||
SetW(_q.xyzw * RcpEstNR(s), half_angle + half_angle));
|
||||
}
|
||||
|
||||
OZZ_INLINE SimdQuaternion SimdQuaternion::FromVectors(_SimdFloat4 _from,
|
||||
_SimdFloat4 _to) {
|
||||
// http://lolengine.net/blog/2014/02/24/quaternion-from-two-vectors-final
|
||||
const SimdFloat4 norm_from_norm_to =
|
||||
SqrtX(Length3Sqr(_from) * Length3Sqr(_to));
|
||||
const float norm_from_norm_to_x = GetX(norm_from_norm_to);
|
||||
if (norm_from_norm_to_x < 1.e-6f) {
|
||||
return SimdQuaternion::identity();
|
||||
}
|
||||
|
||||
const SimdFloat4 real_part = norm_from_norm_to + Dot3(_from, _to);
|
||||
SimdQuaternion quat;
|
||||
if (GetX(real_part) < 1.e-6f * norm_from_norm_to_x) {
|
||||
// If _from and _to are exactly opposite, rotate 180 degrees around an
|
||||
// arbitrary orthogonal axis. Axis normalization can happen later, when we
|
||||
// normalize the quaternion.
|
||||
float from[4];
|
||||
ozz::math::StorePtrU(_from, from);
|
||||
quat.xyzw = std::abs(from[0]) > std::abs(from[2])
|
||||
? ozz::math::simd_float4::Load(-from[1], from[0], 0.f, 0.f)
|
||||
: ozz::math::simd_float4::Load(0.f, -from[2], from[1], 0.f);
|
||||
} else {
|
||||
// This is the general code path.
|
||||
quat.xyzw = SetW(Cross3(_from, _to), real_part);
|
||||
}
|
||||
return Normalize(quat);
|
||||
}
|
||||
|
||||
OZZ_INLINE SimdQuaternion SimdQuaternion::FromUnitVectors(_SimdFloat4 _from,
|
||||
_SimdFloat4 _to) {
|
||||
// http://lolengine.net/blog/2014/02/24/quaternion-from-two-vectors-final
|
||||
assert(ozz::math::AreAllTrue1(
|
||||
And(IsNormalizedEst3(_from), IsNormalizedEst3(_to))) &&
|
||||
"Input vectors must be normalized.");
|
||||
|
||||
const SimdFloat4 real_part =
|
||||
ozz::math::simd_float4::x_axis() + Dot3(_from, _to);
|
||||
if (GetX(real_part) < 1.e-6f) {
|
||||
// If _from and _to are exactly opposite, rotate 180 degrees around an
|
||||
// arbitrary orthogonal axis.
|
||||
// Normalization isn't needed, as from is already.
|
||||
float from[4];
|
||||
ozz::math::StorePtrU(_from, from);
|
||||
SimdQuaternion quat = {
|
||||
std::abs(from[0]) > std::abs(from[2])
|
||||
? ozz::math::simd_float4::Load(-from[1], from[0], 0.f, 0.f)
|
||||
: ozz::math::simd_float4::Load(0.f, -from[2], from[1], 0.f)};
|
||||
return quat;
|
||||
} else {
|
||||
// This is the general code path.
|
||||
SimdQuaternion quat = {SetW(Cross3(_from, _to), real_part)};
|
||||
return Normalize(quat);
|
||||
}
|
||||
}
|
||||
|
||||
// Computes the transformation of a Quaternion and a vector _v.
|
||||
// This is equivalent to carrying out the quaternion multiplications:
|
||||
// _q.conjugate() * (*this) * _q
|
||||
// w component of the returned vector is undefined.
|
||||
OZZ_INLINE SimdFloat4 TransformVector(const SimdQuaternion& _q,
|
||||
_SimdFloat4 _v) {
|
||||
// http://www.neil.dantam.name/note/dantam-quaternion.pdf
|
||||
// _v + 2.f * cross(_q.xyz, cross(_q.xyz, _v) + _q.w * _v)
|
||||
const SimdFloat4 cross1 = MAdd(SplatW(_q.xyzw), _v, Cross3(_q.xyzw, _v));
|
||||
const SimdFloat4 cross2 = Cross3(_q.xyzw, cross1);
|
||||
return _v + cross2 + cross2;
|
||||
}
|
||||
} // namespace math
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_MATHS_SIMD_QUATERNION_H_
|
||||
@@ -0,0 +1,676 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_MATHS_SOA_FLOAT_H_
|
||||
#define OZZ_OZZ_BASE_MATHS_SOA_FLOAT_H_
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "ozz/base/maths/math_constant.h"
|
||||
#include "ozz/base/maths/simd_math.h"
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace math {
|
||||
|
||||
struct SoaFloat2 {
|
||||
SimdFloat4 x, y;
|
||||
|
||||
static OZZ_INLINE SoaFloat2 Load(_SimdFloat4 _x, _SimdFloat4 _y) {
|
||||
const SoaFloat2 r = {_x, _y};
|
||||
return r;
|
||||
}
|
||||
|
||||
static OZZ_INLINE SoaFloat2 zero() {
|
||||
const SoaFloat2 r = {simd_float4::zero(), simd_float4::zero()};
|
||||
return r;
|
||||
}
|
||||
|
||||
static OZZ_INLINE SoaFloat2 one() {
|
||||
const SoaFloat2 r = {simd_float4::one(), simd_float4::one()};
|
||||
return r;
|
||||
}
|
||||
|
||||
static OZZ_INLINE SoaFloat2 x_axis() {
|
||||
const SoaFloat2 r = {simd_float4::one(), simd_float4::zero()};
|
||||
return r;
|
||||
}
|
||||
|
||||
static OZZ_INLINE SoaFloat2 y_axis() {
|
||||
const SoaFloat2 r = {simd_float4::zero(), simd_float4::one()};
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
struct SoaFloat3 {
|
||||
SimdFloat4 x, y, z;
|
||||
|
||||
static OZZ_INLINE SoaFloat3 Load(_SimdFloat4 _x, _SimdFloat4 _y,
|
||||
_SimdFloat4 _z) {
|
||||
const SoaFloat3 r = {_x, _y, _z};
|
||||
return r;
|
||||
}
|
||||
|
||||
static OZZ_INLINE SoaFloat3 Load(const SoaFloat2& _v, _SimdFloat4 _z) {
|
||||
const SoaFloat3 r = {_v.x, _v.y, _z};
|
||||
return r;
|
||||
}
|
||||
|
||||
static OZZ_INLINE SoaFloat3 zero() {
|
||||
const SoaFloat3 r = {simd_float4::zero(), simd_float4::zero(),
|
||||
simd_float4::zero()};
|
||||
return r;
|
||||
}
|
||||
|
||||
static OZZ_INLINE SoaFloat3 one() {
|
||||
const SoaFloat3 r = {simd_float4::one(), simd_float4::one(),
|
||||
simd_float4::one()};
|
||||
return r;
|
||||
}
|
||||
|
||||
static OZZ_INLINE SoaFloat3 x_axis() {
|
||||
const SoaFloat3 r = {simd_float4::one(), simd_float4::zero(),
|
||||
simd_float4::zero()};
|
||||
return r;
|
||||
}
|
||||
|
||||
static OZZ_INLINE SoaFloat3 y_axis() {
|
||||
const SoaFloat3 r = {simd_float4::zero(), simd_float4::one(),
|
||||
simd_float4::zero()};
|
||||
return r;
|
||||
}
|
||||
|
||||
static OZZ_INLINE SoaFloat3 z_axis() {
|
||||
const SoaFloat3 r = {simd_float4::zero(), simd_float4::zero(),
|
||||
simd_float4::one()};
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
struct SoaFloat4 {
|
||||
SimdFloat4 x, y, z, w;
|
||||
|
||||
static OZZ_INLINE SoaFloat4 Load(_SimdFloat4 _x, _SimdFloat4 _y,
|
||||
_SimdFloat4 _z, const SimdFloat4& _w) {
|
||||
const SoaFloat4 r = {_x, _y, _z, _w};
|
||||
return r;
|
||||
}
|
||||
|
||||
static OZZ_INLINE SoaFloat4 Load(const SoaFloat3& _v, _SimdFloat4 _w) {
|
||||
const SoaFloat4 r = {_v.x, _v.y, _v.z, _w};
|
||||
return r;
|
||||
}
|
||||
|
||||
static OZZ_INLINE SoaFloat4 Load(const SoaFloat2& _v, _SimdFloat4 _z,
|
||||
_SimdFloat4 _w) {
|
||||
const SoaFloat4 r = {_v.x, _v.y, _z, _w};
|
||||
return r;
|
||||
}
|
||||
|
||||
static OZZ_INLINE SoaFloat4 zero() {
|
||||
const SimdFloat4 zero = simd_float4::zero();
|
||||
const SoaFloat4 r = {zero, zero, zero, zero};
|
||||
return r;
|
||||
}
|
||||
|
||||
static OZZ_INLINE SoaFloat4 one() {
|
||||
const SimdFloat4 one = simd_float4::one();
|
||||
const SoaFloat4 r = {one, one, one, one};
|
||||
return r;
|
||||
}
|
||||
|
||||
static OZZ_INLINE SoaFloat4 x_axis() {
|
||||
const SimdFloat4 zero = simd_float4::zero();
|
||||
const SoaFloat4 r = {simd_float4::one(), zero, zero, zero};
|
||||
return r;
|
||||
}
|
||||
|
||||
static OZZ_INLINE SoaFloat4 y_axis() {
|
||||
const SimdFloat4 zero = simd_float4::zero();
|
||||
const SoaFloat4 r = {zero, simd_float4::one(), zero, zero};
|
||||
return r;
|
||||
}
|
||||
|
||||
static OZZ_INLINE SoaFloat4 z_axis() {
|
||||
const SimdFloat4 zero = simd_float4::zero();
|
||||
const SoaFloat4 r = {zero, zero, simd_float4::one(), zero};
|
||||
return r;
|
||||
}
|
||||
|
||||
static OZZ_INLINE SoaFloat4 w_axis() {
|
||||
const SimdFloat4 zero = simd_float4::zero();
|
||||
const SoaFloat4 r = {zero, zero, zero, simd_float4::one()};
|
||||
return r;
|
||||
}
|
||||
};
|
||||
} // namespace math
|
||||
} // namespace ozz
|
||||
|
||||
// Returns per element addition of _a and _b using operator +.
|
||||
OZZ_INLINE ozz::math::SoaFloat4 operator+(const ozz::math::SoaFloat4& _a,
|
||||
const ozz::math::SoaFloat4& _b) {
|
||||
const ozz::math::SoaFloat4 r = {_a.x + _b.x, _a.y + _b.y, _a.z + _b.z,
|
||||
_a.w + _b.w};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE ozz::math::SoaFloat3 operator+(const ozz::math::SoaFloat3& _a,
|
||||
const ozz::math::SoaFloat3& _b) {
|
||||
const ozz::math::SoaFloat3 r = {_a.x + _b.x, _a.y + _b.y, _a.z + _b.z};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE ozz::math::SoaFloat2 operator+(const ozz::math::SoaFloat2& _a,
|
||||
const ozz::math::SoaFloat2& _b) {
|
||||
const ozz::math::SoaFloat2 r = {_a.x + _b.x, _a.y + _b.y};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns per element subtraction of _a and _b using operator -.
|
||||
OZZ_INLINE ozz::math::SoaFloat4 operator-(const ozz::math::SoaFloat4& _a,
|
||||
const ozz::math::SoaFloat4& _b) {
|
||||
const ozz::math::SoaFloat4 r = {_a.x - _b.x, _a.y - _b.y, _a.z - _b.z,
|
||||
_a.w - _b.w};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE ozz::math::SoaFloat3 operator-(const ozz::math::SoaFloat3& _a,
|
||||
const ozz::math::SoaFloat3& _b) {
|
||||
const ozz::math::SoaFloat3 r = {_a.x - _b.x, _a.y - _b.y, _a.z - _b.z};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE ozz::math::SoaFloat2 operator-(const ozz::math::SoaFloat2& _a,
|
||||
const ozz::math::SoaFloat2& _b) {
|
||||
const ozz::math::SoaFloat2 r = {_a.x - _b.x, _a.y - _b.y};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns per element negative value of _v.
|
||||
OZZ_INLINE ozz::math::SoaFloat4 operator-(const ozz::math::SoaFloat4& _v) {
|
||||
const ozz::math::SoaFloat4 r = {-_v.x, -_v.y, -_v.z, -_v.w};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE ozz::math::SoaFloat3 operator-(const ozz::math::SoaFloat3& _v) {
|
||||
const ozz::math::SoaFloat3 r = {-_v.x, -_v.y, -_v.z};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE ozz::math::SoaFloat2 operator-(const ozz::math::SoaFloat2& _v) {
|
||||
const ozz::math::SoaFloat2 r = {-_v.x, -_v.y};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns per element multiplication of _a and _b using operator *.
|
||||
OZZ_INLINE ozz::math::SoaFloat4 operator*(const ozz::math::SoaFloat4& _a,
|
||||
const ozz::math::SoaFloat4& _b) {
|
||||
const ozz::math::SoaFloat4 r = {_a.x * _b.x, _a.y * _b.y, _a.z * _b.z,
|
||||
_a.w * _b.w};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE ozz::math::SoaFloat3 operator*(const ozz::math::SoaFloat3& _a,
|
||||
const ozz::math::SoaFloat3& _b) {
|
||||
const ozz::math::SoaFloat3 r = {_a.x * _b.x, _a.y * _b.y, _a.z * _b.z};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE ozz::math::SoaFloat2 operator*(const ozz::math::SoaFloat2& _a,
|
||||
const ozz::math::SoaFloat2& _b) {
|
||||
const ozz::math::SoaFloat2 r = {_a.x * _b.x, _a.y * _b.y};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns per element multiplication of _a and scalar value _f using
|
||||
// operator *.
|
||||
OZZ_INLINE ozz::math::SoaFloat4 operator*(const ozz::math::SoaFloat4& _a,
|
||||
ozz::math::_SimdFloat4 _f) {
|
||||
const ozz::math::SoaFloat4 r = {_a.x * _f, _a.y * _f, _a.z * _f, _a.w * _f};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE ozz::math::SoaFloat3 operator*(const ozz::math::SoaFloat3& _a,
|
||||
ozz::math::_SimdFloat4 _f) {
|
||||
const ozz::math::SoaFloat3 r = {_a.x * _f, _a.y * _f, _a.z * _f};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE ozz::math::SoaFloat2 operator*(const ozz::math::SoaFloat2& _a,
|
||||
ozz::math::_SimdFloat4 _f) {
|
||||
const ozz::math::SoaFloat2 r = {_a.x * _f, _a.y * _f};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Multiplies _a and _b, then adds _addend.
|
||||
// v = (_a * _b) + _addend
|
||||
OZZ_INLINE ozz::math::SoaFloat2 MAdd(const ozz::math::SoaFloat2& _a,
|
||||
const ozz::math::SoaFloat2& _b,
|
||||
const ozz::math::SoaFloat2& _addend) {
|
||||
const ozz::math::SoaFloat2 r = {ozz::math::MAdd(_a.x, _b.x, _addend.x),
|
||||
ozz::math::MAdd(_a.y, _b.y, _addend.y)};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE ozz::math::SoaFloat3 MAdd(const ozz::math::SoaFloat3& _a,
|
||||
const ozz::math::SoaFloat3& _b,
|
||||
const ozz::math::SoaFloat3& _addend) {
|
||||
const ozz::math::SoaFloat3 r = {ozz::math::MAdd(_a.x, _b.x, _addend.x),
|
||||
ozz::math::MAdd(_a.y, _b.y, _addend.y),
|
||||
ozz::math::MAdd(_a.z, _b.z, _addend.z)};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE ozz::math::SoaFloat4 MAdd(const ozz::math::SoaFloat4& _a,
|
||||
const ozz::math::SoaFloat4& _b,
|
||||
const ozz::math::SoaFloat4& _addend) {
|
||||
const ozz::math::SoaFloat4 r = {ozz::math::MAdd(_a.x, _b.x, _addend.x),
|
||||
ozz::math::MAdd(_a.y, _b.y, _addend.y),
|
||||
ozz::math::MAdd(_a.z, _b.z, _addend.z),
|
||||
ozz::math::MAdd(_a.w, _b.w, _addend.w)};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns per element division of _a and _b using operator /.
|
||||
OZZ_INLINE ozz::math::SoaFloat4 operator/(const ozz::math::SoaFloat4& _a,
|
||||
const ozz::math::SoaFloat4& _b) {
|
||||
const ozz::math::SoaFloat4 r = {_a.x / _b.x, _a.y / _b.y, _a.z / _b.z,
|
||||
_a.w / _b.w};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE ozz::math::SoaFloat3 operator/(const ozz::math::SoaFloat3& _a,
|
||||
const ozz::math::SoaFloat3& _b) {
|
||||
const ozz::math::SoaFloat3 r = {_a.x / _b.x, _a.y / _b.y, _a.z / _b.z};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE ozz::math::SoaFloat2 operator/(const ozz::math::SoaFloat2& _a,
|
||||
const ozz::math::SoaFloat2& _b) {
|
||||
const ozz::math::SoaFloat2 r = {_a.x / _b.x, _a.y / _b.y};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns per element division of _a and scalar value _f using operator/.
|
||||
OZZ_INLINE ozz::math::SoaFloat4 operator/(const ozz::math::SoaFloat4& _a,
|
||||
ozz::math::_SimdFloat4 _f) {
|
||||
const ozz::math::SoaFloat4 r = {_a.x / _f, _a.y / _f, _a.z / _f, _a.w / _f};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE ozz::math::SoaFloat3 operator/(const ozz::math::SoaFloat3& _a,
|
||||
ozz::math::_SimdFloat4 _f) {
|
||||
const ozz::math::SoaFloat3 r = {_a.x / _f, _a.y / _f, _a.z / _f};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE ozz::math::SoaFloat2 operator/(const ozz::math::SoaFloat2& _a,
|
||||
ozz::math::_SimdFloat4 _f) {
|
||||
const ozz::math::SoaFloat2 r = {_a.x / _f, _a.y / _f};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns true if each element of a is less than each element of _b.
|
||||
OZZ_INLINE ozz::math::SimdInt4 operator<(const ozz::math::SoaFloat4& _a,
|
||||
const ozz::math::SoaFloat4& _b) {
|
||||
const ozz::math::SimdInt4 x = ozz::math::CmpLt(_a.x, _b.x);
|
||||
const ozz::math::SimdInt4 y = ozz::math::CmpLt(_a.y, _b.y);
|
||||
const ozz::math::SimdInt4 z = ozz::math::CmpLt(_a.z, _b.z);
|
||||
const ozz::math::SimdInt4 w = ozz::math::CmpLt(_a.w, _b.w);
|
||||
return ozz::math::And(ozz::math::And(ozz::math::And(x, y), z), w);
|
||||
}
|
||||
OZZ_INLINE ozz::math::SimdInt4 operator<(const ozz::math::SoaFloat3& _a,
|
||||
const ozz::math::SoaFloat3& _b) {
|
||||
const ozz::math::SimdInt4 x = ozz::math::CmpLt(_a.x, _b.x);
|
||||
const ozz::math::SimdInt4 y = ozz::math::CmpLt(_a.y, _b.y);
|
||||
const ozz::math::SimdInt4 z = ozz::math::CmpLt(_a.z, _b.z);
|
||||
return ozz::math::And(ozz::math::And(x, y), z);
|
||||
}
|
||||
OZZ_INLINE ozz::math::SimdInt4 operator<(const ozz::math::SoaFloat2& _a,
|
||||
const ozz::math::SoaFloat2& _b) {
|
||||
const ozz::math::SimdInt4 x = ozz::math::CmpLt(_a.x, _b.x);
|
||||
const ozz::math::SimdInt4 y = ozz::math::CmpLt(_a.y, _b.y);
|
||||
return ozz::math::And(x, y);
|
||||
}
|
||||
|
||||
// Returns true if each element of a is less or equal to each element of _b.
|
||||
OZZ_INLINE ozz::math::SimdInt4 operator<=(const ozz::math::SoaFloat4& _a,
|
||||
const ozz::math::SoaFloat4& _b) {
|
||||
const ozz::math::SimdInt4 x = ozz::math::CmpLe(_a.x, _b.x);
|
||||
const ozz::math::SimdInt4 y = ozz::math::CmpLe(_a.y, _b.y);
|
||||
const ozz::math::SimdInt4 z = ozz::math::CmpLe(_a.z, _b.z);
|
||||
const ozz::math::SimdInt4 w = ozz::math::CmpLe(_a.w, _b.w);
|
||||
return ozz::math::And(ozz::math::And(ozz::math::And(x, y), z), w);
|
||||
}
|
||||
OZZ_INLINE ozz::math::SimdInt4 operator<=(const ozz::math::SoaFloat3& _a,
|
||||
const ozz::math::SoaFloat3& _b) {
|
||||
const ozz::math::SimdInt4 x = ozz::math::CmpLe(_a.x, _b.x);
|
||||
const ozz::math::SimdInt4 y = ozz::math::CmpLe(_a.y, _b.y);
|
||||
const ozz::math::SimdInt4 z = ozz::math::CmpLe(_a.z, _b.z);
|
||||
return ozz::math::And(ozz::math::And(x, y), z);
|
||||
}
|
||||
OZZ_INLINE ozz::math::SimdInt4 operator<=(const ozz::math::SoaFloat2& _a,
|
||||
const ozz::math::SoaFloat2& _b) {
|
||||
const ozz::math::SimdInt4 x = ozz::math::CmpLe(_a.x, _b.x);
|
||||
const ozz::math::SimdInt4 y = ozz::math::CmpLe(_a.y, _b.y);
|
||||
return ozz::math::And(x, y);
|
||||
}
|
||||
|
||||
// Returns true if each element of a is greater than each element of _b.
|
||||
OZZ_INLINE ozz::math::SimdInt4 operator>(const ozz::math::SoaFloat4& _a,
|
||||
const ozz::math::SoaFloat4& _b) {
|
||||
const ozz::math::SimdInt4 x = ozz::math::CmpGt(_a.x, _b.x);
|
||||
const ozz::math::SimdInt4 y = ozz::math::CmpGt(_a.y, _b.y);
|
||||
const ozz::math::SimdInt4 z = ozz::math::CmpGt(_a.z, _b.z);
|
||||
const ozz::math::SimdInt4 w = ozz::math::CmpGt(_a.w, _b.w);
|
||||
return ozz::math::And(ozz::math::And(ozz::math::And(x, y), z), w);
|
||||
}
|
||||
OZZ_INLINE ozz::math::SimdInt4 operator>(const ozz::math::SoaFloat3& _a,
|
||||
const ozz::math::SoaFloat3& _b) {
|
||||
const ozz::math::SimdInt4 x = ozz::math::CmpGt(_a.x, _b.x);
|
||||
const ozz::math::SimdInt4 y = ozz::math::CmpGt(_a.y, _b.y);
|
||||
const ozz::math::SimdInt4 z = ozz::math::CmpGt(_a.z, _b.z);
|
||||
return ozz::math::And(ozz::math::And(x, y), z);
|
||||
}
|
||||
OZZ_INLINE ozz::math::SimdInt4 operator>(const ozz::math::SoaFloat2& _a,
|
||||
const ozz::math::SoaFloat2& _b) {
|
||||
const ozz::math::SimdInt4 x = ozz::math::CmpGt(_a.x, _b.x);
|
||||
const ozz::math::SimdInt4 y = ozz::math::CmpGt(_a.y, _b.y);
|
||||
return ozz::math::And(x, y);
|
||||
}
|
||||
|
||||
// Returns true if each element of a is greater or equal to each element of _b.
|
||||
OZZ_INLINE ozz::math::SimdInt4 operator>=(const ozz::math::SoaFloat4& _a,
|
||||
const ozz::math::SoaFloat4& _b) {
|
||||
const ozz::math::SimdInt4 x = ozz::math::CmpGe(_a.x, _b.x);
|
||||
const ozz::math::SimdInt4 y = ozz::math::CmpGe(_a.y, _b.y);
|
||||
const ozz::math::SimdInt4 z = ozz::math::CmpGe(_a.z, _b.z);
|
||||
const ozz::math::SimdInt4 w = ozz::math::CmpGe(_a.w, _b.w);
|
||||
return ozz::math::And(ozz::math::And(ozz::math::And(x, y), z), w);
|
||||
}
|
||||
OZZ_INLINE ozz::math::SimdInt4 operator>=(const ozz::math::SoaFloat3& _a,
|
||||
const ozz::math::SoaFloat3& _b) {
|
||||
const ozz::math::SimdInt4 x = ozz::math::CmpGe(_a.x, _b.x);
|
||||
const ozz::math::SimdInt4 y = ozz::math::CmpGe(_a.y, _b.y);
|
||||
const ozz::math::SimdInt4 z = ozz::math::CmpGe(_a.z, _b.z);
|
||||
return ozz::math::And(ozz::math::And(x, y), z);
|
||||
}
|
||||
OZZ_INLINE ozz::math::SimdInt4 operator>=(const ozz::math::SoaFloat2& _a,
|
||||
const ozz::math::SoaFloat2& _b) {
|
||||
const ozz::math::SimdInt4 x = ozz::math::CmpGe(_a.x, _b.x);
|
||||
const ozz::math::SimdInt4 y = ozz::math::CmpGe(_a.y, _b.y);
|
||||
return ozz::math::And(x, y);
|
||||
}
|
||||
|
||||
// Returns true if each element of _a is equal to each element of _b.
|
||||
// Uses a bitwise comparison of _a and _b, no tolerance is applied.
|
||||
OZZ_INLINE ozz::math::SimdInt4 operator==(const ozz::math::SoaFloat4& _a,
|
||||
const ozz::math::SoaFloat4& _b) {
|
||||
const ozz::math::SimdInt4 x = ozz::math::CmpEq(_a.x, _b.x);
|
||||
const ozz::math::SimdInt4 y = ozz::math::CmpEq(_a.y, _b.y);
|
||||
const ozz::math::SimdInt4 z = ozz::math::CmpEq(_a.z, _b.z);
|
||||
const ozz::math::SimdInt4 w = ozz::math::CmpEq(_a.w, _b.w);
|
||||
return ozz::math::And(ozz::math::And(ozz::math::And(x, y), z), w);
|
||||
}
|
||||
OZZ_INLINE ozz::math::SimdInt4 operator==(const ozz::math::SoaFloat3& _a,
|
||||
const ozz::math::SoaFloat3& _b) {
|
||||
const ozz::math::SimdInt4 x = ozz::math::CmpEq(_a.x, _b.x);
|
||||
const ozz::math::SimdInt4 y = ozz::math::CmpEq(_a.y, _b.y);
|
||||
const ozz::math::SimdInt4 z = ozz::math::CmpEq(_a.z, _b.z);
|
||||
return ozz::math::And(ozz::math::And(x, y), z);
|
||||
}
|
||||
OZZ_INLINE ozz::math::SimdInt4 operator==(const ozz::math::SoaFloat2& _a,
|
||||
const ozz::math::SoaFloat2& _b) {
|
||||
const ozz::math::SimdInt4 x = ozz::math::CmpEq(_a.x, _b.x);
|
||||
const ozz::math::SimdInt4 y = ozz::math::CmpEq(_a.y, _b.y);
|
||||
return ozz::math::And(x, y);
|
||||
}
|
||||
|
||||
// Returns true if each element of a is different from each element of _b.
|
||||
// Uses a bitwise comparison of _a and _b, no tolerance is applied.
|
||||
OZZ_INLINE ozz::math::SimdInt4 operator!=(const ozz::math::SoaFloat4& _a,
|
||||
const ozz::math::SoaFloat4& _b) {
|
||||
const ozz::math::SimdInt4 x = ozz::math::CmpNe(_a.x, _b.x);
|
||||
const ozz::math::SimdInt4 y = ozz::math::CmpNe(_a.y, _b.y);
|
||||
const ozz::math::SimdInt4 z = ozz::math::CmpNe(_a.z, _b.z);
|
||||
const ozz::math::SimdInt4 w = ozz::math::CmpNe(_a.w, _b.w);
|
||||
return ozz::math::Or(ozz::math::Or(ozz::math::Or(x, y), z), w);
|
||||
}
|
||||
OZZ_INLINE ozz::math::SimdInt4 operator!=(const ozz::math::SoaFloat3& _a,
|
||||
const ozz::math::SoaFloat3& _b) {
|
||||
const ozz::math::SimdInt4 x = ozz::math::CmpNe(_a.x, _b.x);
|
||||
const ozz::math::SimdInt4 y = ozz::math::CmpNe(_a.y, _b.y);
|
||||
const ozz::math::SimdInt4 z = ozz::math::CmpNe(_a.z, _b.z);
|
||||
return ozz::math::Or(ozz::math::Or(x, y), z);
|
||||
}
|
||||
OZZ_INLINE ozz::math::SimdInt4 operator!=(const ozz::math::SoaFloat2& _a,
|
||||
const ozz::math::SoaFloat2& _b) {
|
||||
const ozz::math::SimdInt4 x = ozz::math::CmpNe(_a.x, _b.x);
|
||||
const ozz::math::SimdInt4 y = ozz::math::CmpNe(_a.y, _b.y);
|
||||
return ozz::math::Or(x, y);
|
||||
}
|
||||
|
||||
namespace ozz {
|
||||
namespace math {
|
||||
|
||||
// Returns the (horizontal) addition of each element of _v.
|
||||
OZZ_INLINE SimdFloat4 HAdd(const SoaFloat4& _v) {
|
||||
return _v.x + _v.y + _v.z + _v.w;
|
||||
}
|
||||
OZZ_INLINE SimdFloat4 HAdd(const SoaFloat3& _v) { return _v.x + _v.y + _v.z; }
|
||||
OZZ_INLINE SimdFloat4 HAdd(const SoaFloat2& _v) { return _v.x + _v.y; }
|
||||
|
||||
// Returns the dot product of _a and _b.
|
||||
OZZ_INLINE SimdFloat4 Dot(const SoaFloat4& _a, const SoaFloat4& _b) {
|
||||
return _a.x * _b.x + _a.y * _b.y + _a.z * _b.z + _a.w * _b.w;
|
||||
}
|
||||
OZZ_INLINE SimdFloat4 Dot(const SoaFloat3& _a, const SoaFloat3& _b) {
|
||||
return _a.x * _b.x + _a.y * _b.y + _a.z * _b.z;
|
||||
}
|
||||
OZZ_INLINE SimdFloat4 Dot(const SoaFloat2& _a, const SoaFloat2& _b) {
|
||||
return _a.x * _b.x + _a.y * _b.y;
|
||||
}
|
||||
|
||||
// Returns the cross product of _a and _b.
|
||||
OZZ_INLINE SoaFloat3 Cross(const SoaFloat3& _a, const SoaFloat3& _b) {
|
||||
const SoaFloat3 r = {_a.y * _b.z - _b.y * _a.z, _a.z * _b.x - _b.z * _a.x,
|
||||
_a.x * _b.y - _b.x * _a.y};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns the length |_v| of _v.
|
||||
OZZ_INLINE SimdFloat4 Length(const SoaFloat4& _v) {
|
||||
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
|
||||
return Sqrt(len2);
|
||||
}
|
||||
OZZ_INLINE SimdFloat4 Length(const SoaFloat3& _v) {
|
||||
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
|
||||
return Sqrt(len2);
|
||||
}
|
||||
OZZ_INLINE SimdFloat4 Length(const SoaFloat2& _v) {
|
||||
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y;
|
||||
return Sqrt(len2);
|
||||
}
|
||||
|
||||
// Returns the square length |_v|^2 of _v.
|
||||
OZZ_INLINE SimdFloat4 LengthSqr(const SoaFloat4& _v) {
|
||||
return _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
|
||||
}
|
||||
OZZ_INLINE SimdFloat4 LengthSqr(const SoaFloat3& _v) {
|
||||
return _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
|
||||
}
|
||||
OZZ_INLINE SimdFloat4 LengthSqr(const SoaFloat2& _v) {
|
||||
return _v.x * _v.x + _v.y * _v.y;
|
||||
}
|
||||
|
||||
// Returns the normalized vector _v.
|
||||
OZZ_INLINE SoaFloat4 Normalize(const SoaFloat4& _v) {
|
||||
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
|
||||
assert(AreAllTrue(CmpNe(len2, simd_float4::zero())) &&
|
||||
"_v is not normalizable");
|
||||
const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
|
||||
const SoaFloat4 r = {_v.x * inv_len, _v.y * inv_len, _v.z * inv_len,
|
||||
_v.w * inv_len};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE SoaFloat3 Normalize(const SoaFloat3& _v) {
|
||||
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
|
||||
assert(AreAllTrue(CmpNe(len2, simd_float4::zero())) &&
|
||||
"_v is not normalizable");
|
||||
const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
|
||||
const SoaFloat3 r = {_v.x * inv_len, _v.y * inv_len, _v.z * inv_len};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE SoaFloat2 Normalize(const SoaFloat2& _v) {
|
||||
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y;
|
||||
assert(AreAllTrue(CmpNe(len2, simd_float4::zero())) &&
|
||||
"_v is not normalizable");
|
||||
const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
|
||||
const SoaFloat2 r = {_v.x * inv_len, _v.y * inv_len};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Test if each vector _v is normalized.
|
||||
OZZ_INLINE math::SimdInt4 IsNormalized(const SoaFloat4& _v) {
|
||||
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
|
||||
return CmpLt(Abs(len2 - math::simd_float4::one()),
|
||||
simd_float4::Load1(kNormalizationToleranceSq));
|
||||
}
|
||||
OZZ_INLINE math::SimdInt4 IsNormalized(const SoaFloat3& _v) {
|
||||
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
|
||||
return CmpLt(Abs(len2 - math::simd_float4::one()),
|
||||
simd_float4::Load1(kNormalizationToleranceSq));
|
||||
}
|
||||
OZZ_INLINE math::SimdInt4 IsNormalized(const SoaFloat2& _v) {
|
||||
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y;
|
||||
return CmpLt(Abs(len2 - math::simd_float4::one()),
|
||||
simd_float4::Load1(kNormalizationToleranceSq));
|
||||
}
|
||||
|
||||
// Test if each vector _v is normalized using estimated tolerance.
|
||||
OZZ_INLINE math::SimdInt4 IsNormalizedEst(const SoaFloat4& _v) {
|
||||
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
|
||||
return CmpLt(Abs(len2 - math::simd_float4::one()),
|
||||
simd_float4::Load1(kNormalizationToleranceEstSq));
|
||||
}
|
||||
OZZ_INLINE math::SimdInt4 IsNormalizedEst(const SoaFloat3& _v) {
|
||||
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
|
||||
return CmpLt(Abs(len2 - math::simd_float4::one()),
|
||||
simd_float4::Load1(kNormalizationToleranceEstSq));
|
||||
}
|
||||
OZZ_INLINE math::SimdInt4 IsNormalizedEst(const SoaFloat2& _v) {
|
||||
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y;
|
||||
return CmpLt(Abs(len2 - math::simd_float4::one()),
|
||||
simd_float4::Load1(kNormalizationToleranceEstSq));
|
||||
}
|
||||
|
||||
// Returns the normalized vector _v if the norm of _v is not 0.
|
||||
// Otherwise returns _safer.
|
||||
OZZ_INLINE SoaFloat4 NormalizeSafe(const SoaFloat4& _v,
|
||||
const SoaFloat4& _safer) {
|
||||
assert(AreAllTrue(IsNormalizedEst(_safer)) && "_safer is not normalized");
|
||||
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
|
||||
const math::SimdInt4 b = CmpNe(len2, math::simd_float4::zero());
|
||||
const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
|
||||
const SoaFloat4 r = {
|
||||
Select(b, _v.x * inv_len, _safer.x), Select(b, _v.y * inv_len, _safer.y),
|
||||
Select(b, _v.z * inv_len, _safer.z), Select(b, _v.w * inv_len, _safer.w)};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE SoaFloat3 NormalizeSafe(const SoaFloat3& _v,
|
||||
const SoaFloat3& _safer) {
|
||||
assert(AreAllTrue(IsNormalizedEst(_safer)) && "_safer is not normalized");
|
||||
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
|
||||
const math::SimdInt4 b = CmpNe(len2, math::simd_float4::zero());
|
||||
const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
|
||||
const SoaFloat3 r = {Select(b, _v.x * inv_len, _safer.x),
|
||||
Select(b, _v.y * inv_len, _safer.y),
|
||||
Select(b, _v.z * inv_len, _safer.z)};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE SoaFloat2 NormalizeSafe(const SoaFloat2& _v,
|
||||
const SoaFloat2& _safer) {
|
||||
assert(AreAllTrue(IsNormalizedEst(_safer)) && "_safer is not normalized");
|
||||
const SimdFloat4 len2 = _v.x * _v.x + _v.y * _v.y;
|
||||
const math::SimdInt4 b = CmpNe(len2, math::simd_float4::zero());
|
||||
const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
|
||||
const SoaFloat2 r = {Select(b, _v.x * inv_len, _safer.x),
|
||||
Select(b, _v.y * inv_len, _safer.y)};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns the linear interpolation of _a and _b with coefficient _f.
|
||||
// _f is not limited to range [0,1].
|
||||
OZZ_INLINE SoaFloat4 Lerp(const SoaFloat4& _a, const SoaFloat4& _b,
|
||||
_SimdFloat4 _f) {
|
||||
const SoaFloat4 r = {(_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
|
||||
(_b.z - _a.z) * _f + _a.z, (_b.w - _a.w) * _f + _a.w};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE SoaFloat3 Lerp(const SoaFloat3& _a, const SoaFloat3& _b,
|
||||
_SimdFloat4 _f) {
|
||||
const SoaFloat3 r = {(_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
|
||||
(_b.z - _a.z) * _f + _a.z};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE SoaFloat2 Lerp(const SoaFloat2& _a, const SoaFloat2& _b,
|
||||
_SimdFloat4 _f) {
|
||||
const SoaFloat2 r = {(_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns the minimum of each element of _a and _b.
|
||||
OZZ_INLINE SoaFloat4 Min(const SoaFloat4& _a, const SoaFloat4& _b) {
|
||||
const SoaFloat4 r = {Min(_a.x, _b.x), Min(_a.y, _b.y), Min(_a.z, _b.z),
|
||||
Min(_a.w, _b.w)};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE SoaFloat3 Min(const SoaFloat3& _a, const SoaFloat3& _b) {
|
||||
const SoaFloat3 r = {Min(_a.x, _b.x), Min(_a.y, _b.y), Min(_a.z, _b.z)};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE SoaFloat2 Min(const SoaFloat2& _a, const SoaFloat2& _b) {
|
||||
const SoaFloat2 r = {Min(_a.x, _b.x), Min(_a.y, _b.y)};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns the maximum of each element of _a and _b.
|
||||
OZZ_INLINE SoaFloat4 Max(const SoaFloat4& _a, const SoaFloat4& _b) {
|
||||
const SoaFloat4 r = {Max(_a.x, _b.x), Max(_a.y, _b.y), Max(_a.z, _b.z),
|
||||
Max(_a.w, _b.w)};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE SoaFloat3 Max(const SoaFloat3& _a, const SoaFloat3& _b) {
|
||||
const SoaFloat3 r = {Max(_a.x, _b.x), Max(_a.y, _b.y), Max(_a.z, _b.z)};
|
||||
return r;
|
||||
}
|
||||
OZZ_INLINE SoaFloat2 Max(const SoaFloat2& _a, const SoaFloat2& _b) {
|
||||
const SoaFloat2 r = {Max(_a.x, _b.x), Max(_a.y, _b.y)};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Clamps each element of _x between _a and _b.
|
||||
// _a must be less or equal to b;
|
||||
OZZ_INLINE SoaFloat4 Clamp(const SoaFloat4& _a, const SoaFloat4& _v,
|
||||
const SoaFloat4& _b) {
|
||||
return Max(_a, Min(_v, _b));
|
||||
}
|
||||
OZZ_INLINE SoaFloat3 Clamp(const SoaFloat3& _a, const SoaFloat3& _v,
|
||||
const SoaFloat3& _b) {
|
||||
return Max(_a, Min(_v, _b));
|
||||
}
|
||||
OZZ_INLINE SoaFloat2 Clamp(const SoaFloat2& _a, const SoaFloat2& _v,
|
||||
const SoaFloat2& _b) {
|
||||
return Max(_a, Min(_v, _b));
|
||||
}
|
||||
} // namespace math
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_MATHS_SOA_FLOAT_H_
|
||||
@@ -0,0 +1,276 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_MATHS_SOA_FLOAT4X4_H_
|
||||
#define OZZ_OZZ_BASE_MATHS_SOA_FLOAT4X4_H_
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "ozz/base/maths/soa_float.h"
|
||||
#include "ozz/base/maths/soa_quaternion.h"
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace math {
|
||||
|
||||
// Declare the 4x4 soa matrix type. Uses the column major convention where the
|
||||
// matrix-times-vector is written v'=Mv:
|
||||
// [ m.cols[0].x m.cols[1].x m.cols[2].x m.cols[3].x ] {v.x}
|
||||
// | m.cols[0].y m.cols[1].y m.cols[2].y m.cols[3].y | * {v.y}
|
||||
// | m.cols[0].z m.cols[1].y m.cols[2].y m.cols[3].y | {v.z}
|
||||
// [ m.cols[0].w m.cols[1].w m.cols[2].w m.cols[3].w ] {v.1}
|
||||
struct SoaFloat4x4 {
|
||||
// Soa matrix columns.
|
||||
SoaFloat4 cols[4];
|
||||
|
||||
// Returns the identity matrix.
|
||||
static OZZ_INLINE SoaFloat4x4 identity() {
|
||||
const SimdFloat4 zero = simd_float4::zero();
|
||||
const SimdFloat4 one = simd_float4::one();
|
||||
SoaFloat4x4 ret = {{{one, zero, zero, zero},
|
||||
{zero, one, zero, zero},
|
||||
{zero, zero, one, zero},
|
||||
{zero, zero, zero, one}}};
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Returns a scaling matrix that scales along _v.
|
||||
// _v.w is ignored.
|
||||
static OZZ_INLINE SoaFloat4x4 Scaling(const SoaFloat4& _v) {
|
||||
const SimdFloat4 zero = simd_float4::zero();
|
||||
const SimdFloat4 one = simd_float4::one();
|
||||
const SoaFloat4x4 ret = {{{_v.x, zero, zero, zero},
|
||||
{zero, _v.y, zero, zero},
|
||||
{zero, zero, _v.z, zero},
|
||||
{zero, zero, zero, one}}};
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Returns the rotation matrix built from quaternion defined by x, y, z and w
|
||||
// components of _v.
|
||||
static OZZ_INLINE SoaFloat4x4 FromQuaternion(const SoaQuaternion& _q) {
|
||||
assert(AreAllTrue(IsNormalizedEst(_q)));
|
||||
|
||||
const SimdFloat4 zero = simd_float4::zero();
|
||||
const SimdFloat4 one = simd_float4::one();
|
||||
const SimdFloat4 two = one + one;
|
||||
|
||||
const SimdFloat4 xx = _q.x * _q.x;
|
||||
const SimdFloat4 xy = _q.x * _q.y;
|
||||
const SimdFloat4 xz = _q.x * _q.z;
|
||||
const SimdFloat4 xw = _q.x * _q.w;
|
||||
const SimdFloat4 yy = _q.y * _q.y;
|
||||
const SimdFloat4 yz = _q.y * _q.z;
|
||||
const SimdFloat4 yw = _q.y * _q.w;
|
||||
const SimdFloat4 zz = _q.z * _q.z;
|
||||
const SimdFloat4 zw = _q.z * _q.w;
|
||||
|
||||
const SoaFloat4x4 ret = {
|
||||
{{one - two * (yy + zz), two * (xy + zw), two * (xz - yw), zero},
|
||||
{two * (xy - zw), one - two * (xx + zz), two * (yz + xw), zero},
|
||||
{two * (xz + yw), two * (yz - xw), one - two * (xx + yy), zero},
|
||||
{zero, zero, zero, one}}};
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Returns the affine transformation matrix built from split translation,
|
||||
// rotation (quaternion) and scale.
|
||||
static OZZ_INLINE SoaFloat4x4 FromAffine(const SoaFloat3& _translation,
|
||||
const SoaQuaternion& _quaternion,
|
||||
const SoaFloat3& _scale) {
|
||||
assert(AreAllTrue(IsNormalizedEst(_quaternion)));
|
||||
|
||||
const SimdFloat4 zero = simd_float4::zero();
|
||||
const SimdFloat4 one = simd_float4::one();
|
||||
const SimdFloat4 two = one + one;
|
||||
|
||||
const SimdFloat4 xx = _quaternion.x * _quaternion.x;
|
||||
const SimdFloat4 xy = _quaternion.x * _quaternion.y;
|
||||
const SimdFloat4 xz = _quaternion.x * _quaternion.z;
|
||||
const SimdFloat4 xw = _quaternion.x * _quaternion.w;
|
||||
const SimdFloat4 yy = _quaternion.y * _quaternion.y;
|
||||
const SimdFloat4 yz = _quaternion.y * _quaternion.z;
|
||||
const SimdFloat4 yw = _quaternion.y * _quaternion.w;
|
||||
const SimdFloat4 zz = _quaternion.z * _quaternion.z;
|
||||
const SimdFloat4 zw = _quaternion.z * _quaternion.w;
|
||||
|
||||
const SoaFloat4x4 ret = {
|
||||
{{_scale.x * (one - two * (yy + zz)), _scale.x * two * (xy + zw),
|
||||
_scale.x * two * (xz - yw), zero},
|
||||
{_scale.y * two * (xy - zw), _scale.y * (one - two * (xx + zz)),
|
||||
_scale.y * two * (yz + xw), zero},
|
||||
{_scale.z * two * (xz + yw), _scale.z * two * (yz - xw),
|
||||
_scale.z * (one - two * (xx + yy)), zero},
|
||||
{_translation.x, _translation.y, _translation.z, one}}};
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
// Returns the transpose of matrix _m.
|
||||
OZZ_INLINE SoaFloat4x4 Transpose(const SoaFloat4x4& _m) {
|
||||
const SoaFloat4x4 ret = {
|
||||
{{_m.cols[0].x, _m.cols[1].x, _m.cols[2].x, _m.cols[3].x},
|
||||
{_m.cols[0].y, _m.cols[1].y, _m.cols[2].y, _m.cols[3].y},
|
||||
{_m.cols[0].z, _m.cols[1].z, _m.cols[2].z, _m.cols[3].z},
|
||||
{_m.cols[0].w, _m.cols[1].w, _m.cols[2].w, _m.cols[3].w}}};
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Returns the inverse of matrix _m.
|
||||
// If _invertible is not nullptr, each component will be set to true if its
|
||||
// respective matrix is invertible. If _invertible is nullptr, then an assert is
|
||||
// triggered in case any of the 4 matrices isn't invertible.
|
||||
OZZ_INLINE SoaFloat4x4 Invert(const SoaFloat4x4& _m,
|
||||
SimdInt4* _invertible = nullptr) {
|
||||
const SoaFloat4* cols = _m.cols;
|
||||
const SimdFloat4 a00 = cols[2].z * cols[3].w - cols[3].z * cols[2].w;
|
||||
const SimdFloat4 a01 = cols[2].y * cols[3].w - cols[3].y * cols[2].w;
|
||||
const SimdFloat4 a02 = cols[2].y * cols[3].z - cols[3].y * cols[2].z;
|
||||
const SimdFloat4 a03 = cols[2].x * cols[3].w - cols[3].x * cols[2].w;
|
||||
const SimdFloat4 a04 = cols[2].x * cols[3].z - cols[3].x * cols[2].z;
|
||||
const SimdFloat4 a05 = cols[2].x * cols[3].y - cols[3].x * cols[2].y;
|
||||
const SimdFloat4 a06 = cols[1].z * cols[3].w - cols[3].z * cols[1].w;
|
||||
const SimdFloat4 a07 = cols[1].y * cols[3].w - cols[3].y * cols[1].w;
|
||||
const SimdFloat4 a08 = cols[1].y * cols[3].z - cols[3].y * cols[1].z;
|
||||
const SimdFloat4 a09 = cols[1].x * cols[3].w - cols[3].x * cols[1].w;
|
||||
const SimdFloat4 a10 = cols[1].x * cols[3].z - cols[3].x * cols[1].z;
|
||||
const SimdFloat4 a11 = cols[1].y * cols[3].w - cols[3].y * cols[1].w;
|
||||
const SimdFloat4 a12 = cols[1].x * cols[3].y - cols[3].x * cols[1].y;
|
||||
const SimdFloat4 a13 = cols[1].z * cols[2].w - cols[2].z * cols[1].w;
|
||||
const SimdFloat4 a14 = cols[1].y * cols[2].w - cols[2].y * cols[1].w;
|
||||
const SimdFloat4 a15 = cols[1].y * cols[2].z - cols[2].y * cols[1].z;
|
||||
const SimdFloat4 a16 = cols[1].x * cols[2].w - cols[2].x * cols[1].w;
|
||||
const SimdFloat4 a17 = cols[1].x * cols[2].z - cols[2].x * cols[1].z;
|
||||
const SimdFloat4 a18 = cols[1].x * cols[2].y - cols[2].x * cols[1].y;
|
||||
|
||||
const SimdFloat4 b0x = cols[1].y * a00 - cols[1].z * a01 + cols[1].w * a02;
|
||||
const SimdFloat4 b1x = -cols[1].x * a00 + cols[1].z * a03 - cols[1].w * a04;
|
||||
const SimdFloat4 b2x = cols[1].x * a01 - cols[1].y * a03 + cols[1].w * a05;
|
||||
const SimdFloat4 b3x = -cols[1].x * a02 + cols[1].y * a04 - cols[1].z * a05;
|
||||
|
||||
const SimdFloat4 b0y = -cols[0].y * a00 + cols[0].z * a01 - cols[0].w * a02;
|
||||
const SimdFloat4 b1y = cols[0].x * a00 - cols[0].z * a03 + cols[0].w * a04;
|
||||
const SimdFloat4 b2y = -cols[0].x * a01 + cols[0].y * a03 - cols[0].w * a05;
|
||||
const SimdFloat4 b3y = cols[0].x * a02 - cols[0].y * a04 + cols[0].z * a05;
|
||||
|
||||
const SimdFloat4 b0z = cols[0].y * a06 - cols[0].z * a07 + cols[0].w * a08;
|
||||
const SimdFloat4 b1z = -cols[0].x * a06 + cols[0].z * a09 - cols[0].w * a10;
|
||||
const SimdFloat4 b2z = cols[0].x * a11 - cols[0].y * a09 + cols[0].w * a12;
|
||||
const SimdFloat4 b3z = -cols[0].x * a08 + cols[0].y * a10 - cols[0].z * a12;
|
||||
|
||||
const SimdFloat4 b0w = -cols[0].y * a13 + cols[0].z * a14 - cols[0].w * a15;
|
||||
const SimdFloat4 b1w = cols[0].x * a13 - cols[0].z * a16 + cols[0].w * a17;
|
||||
const SimdFloat4 b2w = -cols[0].x * a14 + cols[0].y * a16 - cols[0].w * a18;
|
||||
const SimdFloat4 b3w = cols[0].x * a15 - cols[0].y * a17 + cols[0].z * a18;
|
||||
|
||||
const SimdFloat4 det =
|
||||
cols[0].x * b0x + cols[0].y * b1x + cols[0].z * b2x + cols[0].w * b3x;
|
||||
const SimdInt4 invertible = CmpNe(det, simd_float4::zero());
|
||||
assert((_invertible || AreAllTrue(invertible)) && "Matrix is not invertible");
|
||||
if (_invertible != nullptr) {
|
||||
*_invertible = invertible;
|
||||
}
|
||||
const SimdFloat4 inv_det =
|
||||
Select(invertible, RcpEstNR(det), simd_float4::zero());
|
||||
|
||||
const SoaFloat4x4 ret = {
|
||||
{{b0x * inv_det, b0y * inv_det, b0z * inv_det, b0w * inv_det},
|
||||
{b1x * inv_det, b1y * inv_det, b1z * inv_det, b1w * inv_det},
|
||||
{b2x * inv_det, b2y * inv_det, b2z * inv_det, b2w * inv_det},
|
||||
{b3x * inv_det, b3y * inv_det, b3z * inv_det, b3w * inv_det}}};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Scales matrix _m along the axis defined by _v components.
|
||||
// _v.w is ignored.
|
||||
OZZ_INLINE SoaFloat4x4 Scale(const SoaFloat4x4& _m, const SoaFloat4& _v) {
|
||||
const SoaFloat4x4 ret = {{{_m.cols[0].x * _v.x, _m.cols[0].y * _v.x,
|
||||
_m.cols[0].z * _v.x, _m.cols[0].w * _v.x},
|
||||
{_m.cols[1].x * _v.y, _m.cols[1].y * _v.y,
|
||||
_m.cols[1].z * _v.y, _m.cols[1].w * _v.y},
|
||||
{_m.cols[2].x * _v.z, _m.cols[2].y * _v.z,
|
||||
_m.cols[2].z * _v.z, _m.cols[2].w * _v.z},
|
||||
_m.cols[3]}};
|
||||
return ret;
|
||||
}
|
||||
} // namespace math
|
||||
} // namespace ozz
|
||||
|
||||
// Computes the multiplication of matrix Float4x4 and vector _v.
|
||||
OZZ_INLINE ozz::math::SoaFloat4 operator*(const ozz::math::SoaFloat4x4& _m,
|
||||
const ozz::math::SoaFloat4& _v) {
|
||||
const ozz::math::SoaFloat4 ret = {
|
||||
_m.cols[0].x * _v.x + _m.cols[1].x * _v.y + _m.cols[2].x * _v.z +
|
||||
_m.cols[3].x * _v.w,
|
||||
_m.cols[0].y * _v.x + _m.cols[1].y * _v.y + _m.cols[2].y * _v.z +
|
||||
_m.cols[3].y * _v.w,
|
||||
_m.cols[0].z * _v.x + _m.cols[1].z * _v.y + _m.cols[2].z * _v.z +
|
||||
_m.cols[3].z * _v.w,
|
||||
_m.cols[0].w * _v.x + _m.cols[1].w * _v.y + _m.cols[2].w * _v.z +
|
||||
_m.cols[3].w * _v.w};
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Computes the multiplication of two matrices _a and _b.
|
||||
OZZ_INLINE ozz::math::SoaFloat4x4 operator*(const ozz::math::SoaFloat4x4& _a,
|
||||
const ozz::math::SoaFloat4x4& _b) {
|
||||
const ozz::math::SoaFloat4x4 ret = {
|
||||
{_a * _b.cols[0], _a * _b.cols[1], _a * _b.cols[2], _a * _b.cols[3]}};
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Computes the per element addition of two matrices _a and _b.
|
||||
OZZ_INLINE ozz::math::SoaFloat4x4 operator+(const ozz::math::SoaFloat4x4& _a,
|
||||
const ozz::math::SoaFloat4x4& _b) {
|
||||
const ozz::math::SoaFloat4x4 ret = {
|
||||
{{_a.cols[0].x + _b.cols[0].x, _a.cols[0].y + _b.cols[0].y,
|
||||
_a.cols[0].z + _b.cols[0].z, _a.cols[0].w + _b.cols[0].w},
|
||||
{_a.cols[1].x + _b.cols[1].x, _a.cols[1].y + _b.cols[1].y,
|
||||
_a.cols[1].z + _b.cols[1].z, _a.cols[1].w + _b.cols[1].w},
|
||||
{_a.cols[2].x + _b.cols[2].x, _a.cols[2].y + _b.cols[2].y,
|
||||
_a.cols[2].z + _b.cols[2].z, _a.cols[2].w + _b.cols[2].w},
|
||||
{_a.cols[3].x + _b.cols[3].x, _a.cols[3].y + _b.cols[3].y,
|
||||
_a.cols[3].z + _b.cols[3].z, _a.cols[3].w + _b.cols[3].w}}};
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Computes the per element subtraction of two matrices _a and _b.
|
||||
OZZ_INLINE ozz::math::SoaFloat4x4 operator-(const ozz::math::SoaFloat4x4& _a,
|
||||
const ozz::math::SoaFloat4x4& _b) {
|
||||
const ozz::math::SoaFloat4x4 ret = {
|
||||
{{_a.cols[0].x - _b.cols[0].x, _a.cols[0].y - _b.cols[0].y,
|
||||
_a.cols[0].z - _b.cols[0].z, _a.cols[0].w - _b.cols[0].w},
|
||||
{_a.cols[1].x - _b.cols[1].x, _a.cols[1].y - _b.cols[1].y,
|
||||
_a.cols[1].z - _b.cols[1].z, _a.cols[1].w - _b.cols[1].w},
|
||||
{_a.cols[2].x - _b.cols[2].x, _a.cols[2].y - _b.cols[2].y,
|
||||
_a.cols[2].z - _b.cols[2].z, _a.cols[2].w - _b.cols[2].w},
|
||||
{_a.cols[3].x - _b.cols[3].x, _a.cols[3].y - _b.cols[3].y,
|
||||
_a.cols[3].z - _b.cols[3].z, _a.cols[3].w - _b.cols[3].w}}};
|
||||
return ret;
|
||||
}
|
||||
#endif // OZZ_OZZ_BASE_MATHS_SOA_FLOAT4X4_H_
|
||||
@@ -0,0 +1,99 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_MATHS_SOA_MATH_ARCHIVE_H_
|
||||
#define OZZ_OZZ_BASE_MATHS_SOA_MATH_ARCHIVE_H_
|
||||
|
||||
#include "ozz/base/io/archive_traits.h"
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace math {
|
||||
struct SoaFloat2;
|
||||
struct SoaFloat3;
|
||||
struct SoaFloat4;
|
||||
struct SoaQuaternion;
|
||||
struct SoaFloat4x4;
|
||||
struct SoaTransform;
|
||||
} // namespace math
|
||||
namespace io {
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(math::SoaFloat2)
|
||||
template <>
|
||||
struct Extern<math::SoaFloat2> {
|
||||
static void Save(OArchive& _archive, const math::SoaFloat2* _values,
|
||||
size_t _count);
|
||||
static void Load(IArchive& _archive, math::SoaFloat2* _values, size_t _count,
|
||||
uint32_t _version);
|
||||
};
|
||||
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(math::SoaFloat3)
|
||||
template <>
|
||||
struct Extern<math::SoaFloat3> {
|
||||
static void Save(OArchive& _archive, const math::SoaFloat3* _values,
|
||||
size_t _count);
|
||||
static void Load(IArchive& _archive, math::SoaFloat3* _values, size_t _count,
|
||||
uint32_t _version);
|
||||
};
|
||||
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(math::SoaFloat4)
|
||||
template <>
|
||||
struct Extern<math::SoaFloat4> {
|
||||
static void Save(OArchive& _archive, const math::SoaFloat4* _values,
|
||||
size_t _count);
|
||||
static void Load(IArchive& _archive, math::SoaFloat4* _values, size_t _count,
|
||||
uint32_t _version);
|
||||
};
|
||||
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(math::SoaQuaternion)
|
||||
template <>
|
||||
struct Extern<math::SoaQuaternion> {
|
||||
static void Save(OArchive& _archive, const math::SoaQuaternion* _values,
|
||||
size_t _count);
|
||||
static void Load(IArchive& _archive, math::SoaQuaternion* _values,
|
||||
size_t _count, uint32_t _version);
|
||||
};
|
||||
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(math::SoaFloat4x4)
|
||||
template <>
|
||||
struct Extern<math::SoaFloat4x4> {
|
||||
static void Save(OArchive& _archive, const math::SoaFloat4x4* _values,
|
||||
size_t _count);
|
||||
static void Load(IArchive& _archive, math::SoaFloat4x4* _values,
|
||||
size_t _count, uint32_t _version);
|
||||
};
|
||||
|
||||
OZZ_IO_TYPE_NOT_VERSIONABLE(math::SoaTransform)
|
||||
template <>
|
||||
struct Extern<math::SoaTransform> {
|
||||
static void Save(OArchive& _archive, const math::SoaTransform* _values,
|
||||
size_t _count);
|
||||
static void Load(IArchive& _archive, math::SoaTransform* _values,
|
||||
size_t _count, uint32_t _version);
|
||||
};
|
||||
} // namespace io
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_MATHS_SOA_MATH_ARCHIVE_H_
|
||||
@@ -0,0 +1,189 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_MATHS_SOA_QUATERNION_H_
|
||||
#define OZZ_OZZ_BASE_MATHS_SOA_QUATERNION_H_
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "ozz/base/maths/soa_float.h"
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace math {
|
||||
|
||||
struct SoaQuaternion {
|
||||
SimdFloat4 x, y, z, w;
|
||||
|
||||
// Loads a quaternion from 4 SimdFloat4 values.
|
||||
static OZZ_INLINE SoaQuaternion Load(_SimdFloat4 _x, _SimdFloat4 _y,
|
||||
_SimdFloat4 _z, const SimdFloat4& _w) {
|
||||
const SoaQuaternion r = {_x, _y, _z, _w};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns the identity SoaQuaternion.
|
||||
static OZZ_INLINE SoaQuaternion identity() {
|
||||
const SimdFloat4 zero = simd_float4::zero();
|
||||
const SoaQuaternion r = {zero, zero, zero, simd_float4::one()};
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
// Returns the conjugate of _q. This is the same as the inverse if _q is
|
||||
// normalized. Otherwise the magnitude of the inverse is 1.f/|_q|.
|
||||
OZZ_INLINE SoaQuaternion Conjugate(const SoaQuaternion& _q) {
|
||||
const SoaQuaternion r = {-_q.x, -_q.y, -_q.z, _q.w};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns the negate of _q. This represent the same rotation as q.
|
||||
OZZ_INLINE SoaQuaternion operator-(const SoaQuaternion& _q) {
|
||||
const SoaQuaternion r = {-_q.x, -_q.y, -_q.z, -_q.w};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns the 4D dot product of quaternion _a and _b.
|
||||
OZZ_INLINE SimdFloat4 Dot(const SoaQuaternion& _a, const SoaQuaternion& _b) {
|
||||
return _a.x * _b.x + _a.y * _b.y + _a.z * _b.z + _a.w * _b.w;
|
||||
}
|
||||
|
||||
// Returns the normalized SoaQuaternion _q.
|
||||
OZZ_INLINE SoaQuaternion Normalize(const SoaQuaternion& _q) {
|
||||
const SimdFloat4 len2 = _q.x * _q.x + _q.y * _q.y + _q.z * _q.z + _q.w * _q.w;
|
||||
const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
|
||||
const SoaQuaternion r = {_q.x * inv_len, _q.y * inv_len, _q.z * inv_len,
|
||||
_q.w * inv_len};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns the estimated normalized SoaQuaternion _q.
|
||||
OZZ_INLINE SoaQuaternion NormalizeEst(const SoaQuaternion& _q) {
|
||||
const SimdFloat4 len2 = _q.x * _q.x + _q.y * _q.y + _q.z * _q.z + _q.w * _q.w;
|
||||
// Uses RSqrtEstNR (with one more Newton-Raphson step) as quaternions loose
|
||||
// much precision due to normalization.
|
||||
const SimdFloat4 inv_len = RSqrtEstNR(len2);
|
||||
const SoaQuaternion r = {_q.x * inv_len, _q.y * inv_len, _q.z * inv_len,
|
||||
_q.w * inv_len};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Test if each quaternion of _q is normalized.
|
||||
OZZ_INLINE SimdInt4 IsNormalized(const SoaQuaternion& _q) {
|
||||
const SimdFloat4 len2 = _q.x * _q.x + _q.y * _q.y + _q.z * _q.z + _q.w * _q.w;
|
||||
return CmpLt(Abs(len2 - math::simd_float4::one()),
|
||||
simd_float4::Load1(kNormalizationToleranceSq));
|
||||
}
|
||||
|
||||
// Test if each quaternion of _q is normalized. using estimated tolerance.
|
||||
OZZ_INLINE SimdInt4 IsNormalizedEst(const SoaQuaternion& _q) {
|
||||
const SimdFloat4 len2 = _q.x * _q.x + _q.y * _q.y + _q.z * _q.z + _q.w * _q.w;
|
||||
return CmpLt(Abs(len2 - math::simd_float4::one()),
|
||||
simd_float4::Load1(kNormalizationToleranceEstSq));
|
||||
}
|
||||
|
||||
// Returns the linear interpolation of SoaQuaternion _a and _b with coefficient
|
||||
// _f.
|
||||
OZZ_INLINE SoaQuaternion Lerp(const SoaQuaternion& _a, const SoaQuaternion& _b,
|
||||
_SimdFloat4 _f) {
|
||||
const SoaQuaternion r = {(_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
|
||||
(_b.z - _a.z) * _f + _a.z,
|
||||
(_b.w - _a.w) * _f + _a.w};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns the linear interpolation of SoaQuaternion _a and _b with coefficient
|
||||
// _f.
|
||||
OZZ_INLINE SoaQuaternion NLerp(const SoaQuaternion& _a, const SoaQuaternion& _b,
|
||||
_SimdFloat4 _f) {
|
||||
const SoaFloat4 lerp = {(_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
|
||||
(_b.z - _a.z) * _f + _a.z, (_b.w - _a.w) * _f + _a.w};
|
||||
const SimdFloat4 len2 =
|
||||
lerp.x * lerp.x + lerp.y * lerp.y + lerp.z * lerp.z + lerp.w * lerp.w;
|
||||
const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
|
||||
const SoaQuaternion r = {lerp.x * inv_len, lerp.y * inv_len, lerp.z * inv_len,
|
||||
lerp.w * inv_len};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns the estimated linear interpolation of SoaQuaternion _a and _b with
|
||||
// coefficient _f.
|
||||
OZZ_INLINE SoaQuaternion NLerpEst(const SoaQuaternion& _a,
|
||||
const SoaQuaternion& _b, _SimdFloat4 _f) {
|
||||
const SoaFloat4 lerp = {(_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
|
||||
(_b.z - _a.z) * _f + _a.z, (_b.w - _a.w) * _f + _a.w};
|
||||
const SimdFloat4 len2 =
|
||||
lerp.x * lerp.x + lerp.y * lerp.y + lerp.z * lerp.z + lerp.w * lerp.w;
|
||||
// Uses RSqrtEstNR (with one more Newton-Raphson step) as quaternions loose
|
||||
// much precision due to normalization.
|
||||
const SimdFloat4 inv_len = RSqrtEstNR(len2);
|
||||
const SoaQuaternion r = {lerp.x * inv_len, lerp.y * inv_len, lerp.z * inv_len,
|
||||
lerp.w * inv_len};
|
||||
return r;
|
||||
}
|
||||
} // namespace math
|
||||
} // namespace ozz
|
||||
|
||||
// Returns the addition of _a and _b.
|
||||
OZZ_INLINE ozz::math::SoaQuaternion operator+(
|
||||
const ozz::math::SoaQuaternion& _a, const ozz::math::SoaQuaternion& _b) {
|
||||
const ozz::math::SoaQuaternion r = {_a.x + _b.x, _a.y + _b.y, _a.z + _b.z,
|
||||
_a.w + _b.w};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns the multiplication of _q and scalar value _f.
|
||||
OZZ_INLINE ozz::math::SoaQuaternion operator*(
|
||||
const ozz::math::SoaQuaternion& _q, const ozz::math::SimdFloat4& _f) {
|
||||
const ozz::math::SoaQuaternion r = {_q.x * _f, _q.y * _f, _q.z * _f,
|
||||
_q.w * _f};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns the multiplication of _a and _b. If both _a and _b are normalized,
|
||||
// then the result is normalized.
|
||||
OZZ_INLINE ozz::math::SoaQuaternion operator*(
|
||||
const ozz::math::SoaQuaternion& _a, const ozz::math::SoaQuaternion& _b) {
|
||||
const ozz::math::SoaQuaternion r = {
|
||||
_a.w * _b.x + _a.x * _b.w + _a.y * _b.z - _a.z * _b.y,
|
||||
_a.w * _b.y + _a.y * _b.w + _a.z * _b.x - _a.x * _b.z,
|
||||
_a.w * _b.z + _a.z * _b.w + _a.x * _b.y - _a.y * _b.x,
|
||||
_a.w * _b.w - _a.x * _b.x - _a.y * _b.y - _a.z * _b.z};
|
||||
return r;
|
||||
}
|
||||
|
||||
// Returns true if each element of _a is equal to each element of _b.
|
||||
// Uses a bitwise comparison of _a and _b, no tolerance is applied.
|
||||
OZZ_INLINE ozz::math::SimdInt4 operator==(const ozz::math::SoaQuaternion& _a,
|
||||
const ozz::math::SoaQuaternion& _b) {
|
||||
const ozz::math::SimdInt4 x = ozz::math::CmpEq(_a.x, _b.x);
|
||||
const ozz::math::SimdInt4 y = ozz::math::CmpEq(_a.y, _b.y);
|
||||
const ozz::math::SimdInt4 z = ozz::math::CmpEq(_a.z, _b.z);
|
||||
const ozz::math::SimdInt4 w = ozz::math::CmpEq(_a.w, _b.w);
|
||||
return ozz::math::And(ozz::math::And(ozz::math::And(x, y), z), w);
|
||||
}
|
||||
#endif // OZZ_OZZ_BASE_MATHS_SOA_QUATERNION_H_
|
||||
@@ -0,0 +1,53 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_MATHS_SOA_TRANSFORM_H_
|
||||
#define OZZ_OZZ_BASE_MATHS_SOA_TRANSFORM_H_
|
||||
|
||||
#include "ozz/base/maths/soa_float.h"
|
||||
#include "ozz/base/maths/soa_quaternion.h"
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace math {
|
||||
|
||||
// Stores an affine transformation with separate translation, rotation and scale
|
||||
// attributes.
|
||||
struct SoaTransform {
|
||||
SoaFloat3 translation;
|
||||
SoaQuaternion rotation;
|
||||
SoaFloat3 scale;
|
||||
|
||||
static OZZ_INLINE SoaTransform identity() {
|
||||
const SoaTransform ret = {SoaFloat3::zero(), SoaQuaternion::identity(),
|
||||
SoaFloat3::one()};
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
} // namespace math
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_MATHS_SOA_TRANSFORM_H_
|
||||
@@ -0,0 +1,59 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_MATHS_TRANSFORM_H_
|
||||
#define OZZ_OZZ_BASE_MATHS_TRANSFORM_H_
|
||||
|
||||
#include "ozz/base/maths/quaternion.h"
|
||||
#include "ozz/base/maths/vec_float.h"
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace math {
|
||||
|
||||
// Stores an affine transformation with separate translation, rotation and scale
|
||||
// attributes.
|
||||
struct Transform {
|
||||
// Translation affine transformation component.
|
||||
Float3 translation;
|
||||
|
||||
// Rotation affine transformation component.
|
||||
Quaternion rotation;
|
||||
|
||||
// Scale affine transformation component.
|
||||
Float3 scale;
|
||||
|
||||
// Builds an identity transform.
|
||||
static OZZ_INLINE Transform identity() {
|
||||
const Transform ret = {Float3::zero(), Quaternion::identity(),
|
||||
Float3::one()};
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
} // namespace math
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_MATHS_TRANSFORM_H_
|
||||
@@ -0,0 +1,467 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_MATHS_VEC_FLOAT_H_
|
||||
#define OZZ_OZZ_BASE_MATHS_VEC_FLOAT_H_
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
#include "ozz/base/maths/math_constant.h"
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace math {
|
||||
|
||||
// Declares a 2d float vector.
|
||||
struct Float2 {
|
||||
float x, y;
|
||||
|
||||
// Constructs an uninitialized vector.
|
||||
OZZ_INLINE Float2() {}
|
||||
|
||||
// Constructs a vector initialized with _f value.
|
||||
explicit OZZ_INLINE Float2(float _f) : x(_f), y(_f) {}
|
||||
|
||||
// Constructs a vector initialized with _x and _y values.
|
||||
OZZ_INLINE Float2(float _x, float _y) : x(_x), y(_y) {}
|
||||
|
||||
// Returns a vector with all components set to 0.
|
||||
static OZZ_INLINE Float2 zero() { return Float2(0.f); }
|
||||
|
||||
// Returns a vector with all components set to 1.
|
||||
static OZZ_INLINE Float2 one() { return Float2(1.f); }
|
||||
|
||||
// Returns a unitary vector x.
|
||||
static OZZ_INLINE Float2 x_axis() { return Float2(1.f, 0.f); }
|
||||
|
||||
// Returns a unitary vector y.
|
||||
static OZZ_INLINE Float2 y_axis() { return Float2(0.f, 1.f); }
|
||||
};
|
||||
|
||||
// Declares a 3d float vector.
|
||||
struct Float3 {
|
||||
float x, y, z;
|
||||
|
||||
// Constructs an uninitialized vector.
|
||||
OZZ_INLINE Float3() {}
|
||||
|
||||
// Constructs a vector initialized with _f value.
|
||||
explicit OZZ_INLINE Float3(float _f) : x(_f), y(_f), z(_f) {}
|
||||
|
||||
// Constructs a vector initialized with _x, _y and _z values.
|
||||
OZZ_INLINE Float3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
|
||||
|
||||
// Returns a vector initialized with _v.x, _v.y and _z values.
|
||||
OZZ_INLINE Float3(Float2 _v, float _z) : x(_v.x), y(_v.y), z(_z) {}
|
||||
|
||||
// Returns a vector with all components set to 0.
|
||||
static OZZ_INLINE Float3 zero() { return Float3(0.f); }
|
||||
|
||||
// Returns a vector with all components set to 1.
|
||||
static OZZ_INLINE Float3 one() { return Float3(1.f); }
|
||||
|
||||
// Returns a unitary vector x.
|
||||
static OZZ_INLINE Float3 x_axis() { return Float3(1.f, 0.f, 0.f); }
|
||||
|
||||
// Returns a unitary vector y.
|
||||
static OZZ_INLINE Float3 y_axis() { return Float3(0.f, 1.f, 0.f); }
|
||||
|
||||
// Returns a unitary vector z.
|
||||
static OZZ_INLINE Float3 z_axis() { return Float3(0.f, 0.f, 1.f); }
|
||||
};
|
||||
|
||||
// Declares a 4d float vector.
|
||||
struct Float4 {
|
||||
float x, y, z, w;
|
||||
|
||||
// Constructs an uninitialized vector.
|
||||
OZZ_INLINE Float4() {}
|
||||
|
||||
// Constructs a vector initialized with _f value.
|
||||
explicit OZZ_INLINE Float4(float _f) : x(_f), y(_f), z(_f), w(_f) {}
|
||||
|
||||
// Constructs a vector initialized with _x, _y, _z and _w values.
|
||||
OZZ_INLINE Float4(float _x, float _y, float _z, float _w)
|
||||
: x(_x), y(_y), z(_z), w(_w) {}
|
||||
|
||||
// Constructs a vector initialized with _v.x, _v.y, _v.z and _w values.
|
||||
OZZ_INLINE Float4(Float3 _v, float _w) : x(_v.x), y(_v.y), z(_v.z), w(_w) {}
|
||||
|
||||
// Constructs a vector initialized with _v.x, _v.y, _z and _w values.
|
||||
OZZ_INLINE Float4(Float2 _v, float _z, float _w)
|
||||
: x(_v.x), y(_v.y), z(_z), w(_w) {}
|
||||
|
||||
// Returns a vector with all components set to 0.
|
||||
static OZZ_INLINE Float4 zero() { return Float4(0.f); }
|
||||
|
||||
// Returns a vector with all components set to 1.
|
||||
static OZZ_INLINE Float4 one() { return Float4(1.f); }
|
||||
|
||||
// Returns a unitary vector x.
|
||||
static OZZ_INLINE Float4 x_axis() { return Float4(1.f, 0.f, 0.f, 0.f); }
|
||||
|
||||
// Returns a unitary vector y.
|
||||
static OZZ_INLINE Float4 y_axis() { return Float4(0.f, 1.f, 0.f, 0.f); }
|
||||
|
||||
// Returns a unitary vector z.
|
||||
static OZZ_INLINE Float4 z_axis() { return Float4(0.f, 0.f, 1.f, 0.f); }
|
||||
|
||||
// Returns a unitary vector w.
|
||||
static OZZ_INLINE Float4 w_axis() { return Float4(0.f, 0.f, 0.f, 1.f); }
|
||||
};
|
||||
|
||||
// Returns per element addition of _a and _b using operator +.
|
||||
OZZ_INLINE Float4 operator+(const Float4& _a, const Float4& _b) {
|
||||
return Float4(_a.x + _b.x, _a.y + _b.y, _a.z + _b.z, _a.w + _b.w);
|
||||
}
|
||||
OZZ_INLINE Float3 operator+(const Float3& _a, const Float3& _b) {
|
||||
return Float3(_a.x + _b.x, _a.y + _b.y, _a.z + _b.z);
|
||||
}
|
||||
OZZ_INLINE Float2 operator+(const Float2& _a, const Float2& _b) {
|
||||
return Float2(_a.x + _b.x, _a.y + _b.y);
|
||||
}
|
||||
|
||||
// Returns per element subtraction of _a and _b using operator -.
|
||||
OZZ_INLINE Float4 operator-(const Float4& _a, const Float4& _b) {
|
||||
return Float4(_a.x - _b.x, _a.y - _b.y, _a.z - _b.z, _a.w - _b.w);
|
||||
}
|
||||
OZZ_INLINE Float3 operator-(const Float3& _a, const Float3& _b) {
|
||||
return Float3(_a.x - _b.x, _a.y - _b.y, _a.z - _b.z);
|
||||
}
|
||||
OZZ_INLINE Float2 operator-(const Float2& _a, const Float2& _b) {
|
||||
return Float2(_a.x - _b.x, _a.y - _b.y);
|
||||
}
|
||||
|
||||
// Returns per element negative value of _v.
|
||||
OZZ_INLINE Float4 operator-(const Float4& _v) {
|
||||
return Float4(-_v.x, -_v.y, -_v.z, -_v.w);
|
||||
}
|
||||
OZZ_INLINE Float3 operator-(const Float3& _v) {
|
||||
return Float3(-_v.x, -_v.y, -_v.z);
|
||||
}
|
||||
OZZ_INLINE Float2 operator-(const Float2& _v) { return Float2(-_v.x, -_v.y); }
|
||||
|
||||
// Returns per element multiplication of _a and _b using operator *.
|
||||
OZZ_INLINE Float4 operator*(const Float4& _a, const Float4& _b) {
|
||||
return Float4(_a.x * _b.x, _a.y * _b.y, _a.z * _b.z, _a.w * _b.w);
|
||||
}
|
||||
OZZ_INLINE Float3 operator*(const Float3& _a, const Float3& _b) {
|
||||
return Float3(_a.x * _b.x, _a.y * _b.y, _a.z * _b.z);
|
||||
}
|
||||
OZZ_INLINE Float2 operator*(const Float2& _a, const Float2& _b) {
|
||||
return Float2(_a.x * _b.x, _a.y * _b.y);
|
||||
}
|
||||
|
||||
// Returns per element multiplication of _a and scalar value _f using
|
||||
// operator *.
|
||||
OZZ_INLINE Float4 operator*(const Float4& _a, float _f) {
|
||||
return Float4(_a.x * _f, _a.y * _f, _a.z * _f, _a.w * _f);
|
||||
}
|
||||
OZZ_INLINE Float3 operator*(const Float3& _a, float _f) {
|
||||
return Float3(_a.x * _f, _a.y * _f, _a.z * _f);
|
||||
}
|
||||
OZZ_INLINE Float2 operator*(const Float2& _a, float _f) {
|
||||
return Float2(_a.x * _f, _a.y * _f);
|
||||
}
|
||||
|
||||
// Returns per element division of _a and _b using operator /.
|
||||
OZZ_INLINE Float4 operator/(const Float4& _a, const Float4& _b) {
|
||||
return Float4(_a.x / _b.x, _a.y / _b.y, _a.z / _b.z, _a.w / _b.w);
|
||||
}
|
||||
OZZ_INLINE Float3 operator/(const Float3& _a, const Float3& _b) {
|
||||
return Float3(_a.x / _b.x, _a.y / _b.y, _a.z / _b.z);
|
||||
}
|
||||
OZZ_INLINE Float2 operator/(const Float2& _a, const Float2& _b) {
|
||||
return Float2(_a.x / _b.x, _a.y / _b.y);
|
||||
}
|
||||
|
||||
// Returns per element division of _a and scalar value _f using operator/.
|
||||
OZZ_INLINE Float4 operator/(const Float4& _a, float _f) {
|
||||
return Float4(_a.x / _f, _a.y / _f, _a.z / _f, _a.w / _f);
|
||||
}
|
||||
OZZ_INLINE Float3 operator/(const Float3& _a, float _f) {
|
||||
return Float3(_a.x / _f, _a.y / _f, _a.z / _f);
|
||||
}
|
||||
OZZ_INLINE Float2 operator/(const Float2& _a, float _f) {
|
||||
return Float2(_a.x / _f, _a.y / _f);
|
||||
}
|
||||
|
||||
// Returns the (horizontal) addition of each element of _v.
|
||||
OZZ_INLINE float HAdd(const Float4& _v) { return _v.x + _v.y + _v.z + _v.w; }
|
||||
OZZ_INLINE float HAdd(const Float3& _v) { return _v.x + _v.y + _v.z; }
|
||||
OZZ_INLINE float HAdd(const Float2& _v) { return _v.x + _v.y; }
|
||||
|
||||
// Returns the dot product of _a and _b.
|
||||
OZZ_INLINE float Dot(const Float4& _a, const Float4& _b) {
|
||||
return _a.x * _b.x + _a.y * _b.y + _a.z * _b.z + _a.w * _b.w;
|
||||
}
|
||||
OZZ_INLINE float Dot(const Float3& _a, const Float3& _b) {
|
||||
return _a.x * _b.x + _a.y * _b.y + _a.z * _b.z;
|
||||
}
|
||||
OZZ_INLINE float Dot(const Float2& _a, const Float2& _b) {
|
||||
return _a.x * _b.x + _a.y * _b.y;
|
||||
}
|
||||
|
||||
// Returns the cross product of _a and _b.
|
||||
OZZ_INLINE Float3 Cross(const Float3& _a, const Float3& _b) {
|
||||
return Float3(_a.y * _b.z - _b.y * _a.z, _a.z * _b.x - _b.z * _a.x,
|
||||
_a.x * _b.y - _b.x * _a.y);
|
||||
}
|
||||
|
||||
// Returns the length |_v| of _v.
|
||||
OZZ_INLINE float Length(const Float4& _v) {
|
||||
const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
|
||||
return std::sqrt(len2);
|
||||
}
|
||||
OZZ_INLINE float Length(const Float3& _v) {
|
||||
const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
|
||||
return std::sqrt(len2);
|
||||
}
|
||||
OZZ_INLINE float Length(const Float2& _v) {
|
||||
const float len2 = _v.x * _v.x + _v.y * _v.y;
|
||||
return std::sqrt(len2);
|
||||
}
|
||||
|
||||
// Returns the square length |_v|^2 of _v.
|
||||
OZZ_INLINE float LengthSqr(const Float4& _v) {
|
||||
return _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
|
||||
}
|
||||
OZZ_INLINE float LengthSqr(const Float3& _v) {
|
||||
return _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
|
||||
}
|
||||
OZZ_INLINE float LengthSqr(const Float2& _v) {
|
||||
return _v.x * _v.x + _v.y * _v.y;
|
||||
}
|
||||
|
||||
// Returns the normalized vector _v.
|
||||
OZZ_INLINE Float4 Normalize(const Float4& _v) {
|
||||
const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
|
||||
assert(len2 != 0.f && "_v is not normalizable");
|
||||
const float len = std::sqrt(len2);
|
||||
return Float4(_v.x / len, _v.y / len, _v.z / len, _v.w / len);
|
||||
}
|
||||
OZZ_INLINE Float3 Normalize(const Float3& _v) {
|
||||
const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
|
||||
assert(len2 != 0.f && "_v is not normalizable");
|
||||
const float len = std::sqrt(len2);
|
||||
return Float3(_v.x / len, _v.y / len, _v.z / len);
|
||||
}
|
||||
OZZ_INLINE Float2 Normalize(const Float2& _v) {
|
||||
const float len2 = _v.x * _v.x + _v.y * _v.y;
|
||||
assert(len2 != 0.f && "_v is not normalizable");
|
||||
const float len = std::sqrt(len2);
|
||||
return Float2(_v.x / len, _v.y / len);
|
||||
}
|
||||
|
||||
// Returns true if _v is normalized.
|
||||
OZZ_INLINE bool IsNormalized(const Float4& _v) {
|
||||
const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
|
||||
return std::abs(len2 - 1.f) < kNormalizationToleranceSq;
|
||||
}
|
||||
OZZ_INLINE bool IsNormalized(const Float3& _v) {
|
||||
const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
|
||||
return std::abs(len2 - 1.f) < kNormalizationToleranceSq;
|
||||
}
|
||||
OZZ_INLINE bool IsNormalized(const Float2& _v) {
|
||||
const float len2 = _v.x * _v.x + _v.y * _v.y;
|
||||
return std::abs(len2 - 1.f) < kNormalizationToleranceSq;
|
||||
}
|
||||
|
||||
// Returns the normalized vector _v if the norm of _v is not 0.
|
||||
// Otherwise returns _safer.
|
||||
OZZ_INLINE Float4 NormalizeSafe(const Float4& _v, const Float4& _safer) {
|
||||
assert(IsNormalized(_safer) && "_safer is not normalized");
|
||||
const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z + _v.w * _v.w;
|
||||
if (len2 <= 0.f) {
|
||||
return _safer;
|
||||
}
|
||||
const float len = std::sqrt(len2);
|
||||
return Float4(_v.x / len, _v.y / len, _v.z / len, _v.w / len);
|
||||
}
|
||||
OZZ_INLINE Float3 NormalizeSafe(const Float3& _v, const Float3& _safer) {
|
||||
assert(IsNormalized(_safer) && "_safer is not normalized");
|
||||
const float len2 = _v.x * _v.x + _v.y * _v.y + _v.z * _v.z;
|
||||
if (len2 <= 0.f) {
|
||||
return _safer;
|
||||
}
|
||||
const float len = std::sqrt(len2);
|
||||
return Float3(_v.x / len, _v.y / len, _v.z / len);
|
||||
}
|
||||
OZZ_INLINE Float2 NormalizeSafe(const Float2& _v, const Float2& _safer) {
|
||||
assert(IsNormalized(_safer) && "_safer is not normalized");
|
||||
const float len2 = _v.x * _v.x + _v.y * _v.y;
|
||||
if (len2 <= 0.f) {
|
||||
return _safer;
|
||||
}
|
||||
const float len = std::sqrt(len2);
|
||||
return Float2(_v.x / len, _v.y / len);
|
||||
}
|
||||
|
||||
// Returns the linear interpolation of _a and _b with coefficient _f.
|
||||
// _f is not limited to range [0,1].
|
||||
OZZ_INLINE Float4 Lerp(const Float4& _a, const Float4& _b, float _f) {
|
||||
return Float4((_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
|
||||
(_b.z - _a.z) * _f + _a.z, (_b.w - _a.w) * _f + _a.w);
|
||||
}
|
||||
OZZ_INLINE Float3 Lerp(const Float3& _a, const Float3& _b, float _f) {
|
||||
return Float3((_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
|
||||
(_b.z - _a.z) * _f + _a.z);
|
||||
}
|
||||
OZZ_INLINE Float2 Lerp(const Float2& _a, const Float2& _b, float _f) {
|
||||
return Float2((_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y);
|
||||
}
|
||||
|
||||
// Returns true if the distance between _a and _b is less than _tolerance.
|
||||
OZZ_INLINE bool Compare(const Float4& _a, const Float4& _b, float _tolerance) {
|
||||
const math::Float4 diff = _a - _b;
|
||||
return Dot(diff, diff) <= _tolerance * _tolerance;
|
||||
}
|
||||
OZZ_INLINE bool Compare(const Float3& _a, const Float3& _b, float _tolerance) {
|
||||
const math::Float3 diff = _a - _b;
|
||||
return Dot(diff, diff) <= _tolerance * _tolerance;
|
||||
}
|
||||
OZZ_INLINE bool Compare(const Float2& _a, const Float2& _b, float _tolerance) {
|
||||
const math::Float2 diff = _a - _b;
|
||||
return Dot(diff, diff) <= _tolerance * _tolerance;
|
||||
}
|
||||
|
||||
// Returns true if each element of a is less than each element of _b.
|
||||
OZZ_INLINE bool operator<(const Float4& _a, const Float4& _b) {
|
||||
return _a.x < _b.x && _a.y < _b.y && _a.z < _b.z && _a.w < _b.w;
|
||||
}
|
||||
OZZ_INLINE bool operator<(const Float3& _a, const Float3& _b) {
|
||||
return _a.x < _b.x && _a.y < _b.y && _a.z < _b.z;
|
||||
}
|
||||
OZZ_INLINE bool operator<(const Float2& _a, const Float2& _b) {
|
||||
return _a.x < _b.x && _a.y < _b.y;
|
||||
}
|
||||
|
||||
// Returns true if each element of a is less or equal to each element of _b.
|
||||
OZZ_INLINE bool operator<=(const Float4& _a, const Float4& _b) {
|
||||
return _a.x <= _b.x && _a.y <= _b.y && _a.z <= _b.z && _a.w <= _b.w;
|
||||
}
|
||||
OZZ_INLINE bool operator<=(const Float3& _a, const Float3& _b) {
|
||||
return _a.x <= _b.x && _a.y <= _b.y && _a.z <= _b.z;
|
||||
}
|
||||
OZZ_INLINE bool operator<=(const Float2& _a, const Float2& _b) {
|
||||
return _a.x <= _b.x && _a.y <= _b.y;
|
||||
}
|
||||
|
||||
// Returns true if each element of a is greater than each element of _b.
|
||||
OZZ_INLINE bool operator>(const Float4& _a, const Float4& _b) {
|
||||
return _a.x > _b.x && _a.y > _b.y && _a.z > _b.z && _a.w > _b.w;
|
||||
}
|
||||
OZZ_INLINE bool operator>(const Float3& _a, const Float3& _b) {
|
||||
return _a.x > _b.x && _a.y > _b.y && _a.z > _b.z;
|
||||
}
|
||||
OZZ_INLINE bool operator>(const Float2& _a, const Float2& _b) {
|
||||
return _a.x > _b.x && _a.y > _b.y;
|
||||
}
|
||||
|
||||
// Returns true if each element of a is greater or equal to each element of _b.
|
||||
OZZ_INLINE bool operator>=(const Float4& _a, const Float4& _b) {
|
||||
return _a.x >= _b.x && _a.y >= _b.y && _a.z >= _b.z && _a.w >= _b.w;
|
||||
}
|
||||
OZZ_INLINE bool operator>=(const Float3& _a, const Float3& _b) {
|
||||
return _a.x >= _b.x && _a.y >= _b.y && _a.z >= _b.z;
|
||||
}
|
||||
OZZ_INLINE bool operator>=(const Float2& _a, const Float2& _b) {
|
||||
return _a.x >= _b.x && _a.y >= _b.y;
|
||||
}
|
||||
|
||||
// Returns true if each element of a is equal to each element of _b.
|
||||
// Uses a bitwise comparison of _a and _b, no tolerance is applied.
|
||||
OZZ_INLINE bool operator==(const Float4& _a, const Float4& _b) {
|
||||
return _a.x == _b.x && _a.y == _b.y && _a.z == _b.z && _a.w == _b.w;
|
||||
}
|
||||
OZZ_INLINE bool operator==(const Float3& _a, const Float3& _b) {
|
||||
return _a.x == _b.x && _a.y == _b.y && _a.z == _b.z;
|
||||
}
|
||||
OZZ_INLINE bool operator==(const Float2& _a, const Float2& _b) {
|
||||
return _a.x == _b.x && _a.y == _b.y;
|
||||
}
|
||||
|
||||
// Returns true if each element of a is different from each element of _b.
|
||||
// Uses a bitwise comparison of _a and _b, no tolerance is applied.
|
||||
OZZ_INLINE bool operator!=(const Float4& _a, const Float4& _b) {
|
||||
return _a.x != _b.x || _a.y != _b.y || _a.z != _b.z || _a.w != _b.w;
|
||||
}
|
||||
OZZ_INLINE bool operator!=(const Float3& _a, const Float3& _b) {
|
||||
return _a.x != _b.x || _a.y != _b.y || _a.z != _b.z;
|
||||
}
|
||||
OZZ_INLINE bool operator!=(const Float2& _a, const Float2& _b) {
|
||||
return _a.x != _b.x || _a.y != _b.y;
|
||||
}
|
||||
|
||||
// Returns the minimum of each element of _a and _b.
|
||||
OZZ_INLINE Float4 Min(const Float4& _a, const Float4& _b) {
|
||||
return Float4(_a.x < _b.x ? _a.x : _b.x, _a.y < _b.y ? _a.y : _b.y,
|
||||
_a.z < _b.z ? _a.z : _b.z, _a.w < _b.w ? _a.w : _b.w);
|
||||
}
|
||||
OZZ_INLINE Float3 Min(const Float3& _a, const Float3& _b) {
|
||||
return Float3(_a.x < _b.x ? _a.x : _b.x, _a.y < _b.y ? _a.y : _b.y,
|
||||
_a.z < _b.z ? _a.z : _b.z);
|
||||
}
|
||||
OZZ_INLINE Float2 Min(const Float2& _a, const Float2& _b) {
|
||||
return Float2(_a.x < _b.x ? _a.x : _b.x, _a.y < _b.y ? _a.y : _b.y);
|
||||
}
|
||||
|
||||
// Returns the maximum of each element of _a and _b.
|
||||
OZZ_INLINE Float4 Max(const Float4& _a, const Float4& _b) {
|
||||
return Float4(_a.x > _b.x ? _a.x : _b.x, _a.y > _b.y ? _a.y : _b.y,
|
||||
_a.z > _b.z ? _a.z : _b.z, _a.w > _b.w ? _a.w : _b.w);
|
||||
}
|
||||
OZZ_INLINE Float3 Max(const Float3& _a, const Float3& _b) {
|
||||
return Float3(_a.x > _b.x ? _a.x : _b.x, _a.y > _b.y ? _a.y : _b.y,
|
||||
_a.z > _b.z ? _a.z : _b.z);
|
||||
}
|
||||
OZZ_INLINE Float2 Max(const Float2& _a, const Float2& _b) {
|
||||
return Float2(_a.x > _b.x ? _a.x : _b.x, _a.y > _b.y ? _a.y : _b.y);
|
||||
}
|
||||
|
||||
// Clamps each element of _x between _a and _b.
|
||||
// _a must be less or equal to b;
|
||||
OZZ_INLINE Float4 Clamp(const Float4& _a, const Float4& _v, const Float4& _b) {
|
||||
const Float4 min(_v.x < _b.x ? _v.x : _b.x, _v.y < _b.y ? _v.y : _b.y,
|
||||
_v.z < _b.z ? _v.z : _b.z, _v.w < _b.w ? _v.w : _b.w);
|
||||
return Float4(_a.x > min.x ? _a.x : min.x, _a.y > min.y ? _a.y : min.y,
|
||||
_a.z > min.z ? _a.z : min.z, _a.w > min.w ? _a.w : min.w);
|
||||
}
|
||||
OZZ_INLINE Float3 Clamp(const Float3& _a, const Float3& _v, const Float3& _b) {
|
||||
const Float3 min(_v.x < _b.x ? _v.x : _b.x, _v.y < _b.y ? _v.y : _b.y,
|
||||
_v.z < _b.z ? _v.z : _b.z);
|
||||
return Float3(_a.x > min.x ? _a.x : min.x, _a.y > min.y ? _a.y : min.y,
|
||||
_a.z > min.z ? _a.z : min.z);
|
||||
}
|
||||
OZZ_INLINE Float2 Clamp(const Float2& _a, const Float2& _v, const Float2& _b) {
|
||||
const Float2 min(_v.x < _b.x ? _v.x : _b.x, _v.y < _b.y ? _v.y : _b.y);
|
||||
return Float2(_a.x > min.x ? _a.x : min.x, _a.y > min.y ? _a.y : min.y);
|
||||
}
|
||||
} // namespace math
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_MATHS_VEC_FLOAT_H_
|
||||
@@ -0,0 +1,99 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_MEMORY_ALLOCATOR_H_
|
||||
#define OZZ_OZZ_BASE_MEMORY_ALLOCATOR_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <new>
|
||||
#include <utility>
|
||||
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace memory {
|
||||
|
||||
// Forwards declare Allocator class.
|
||||
class Allocator;
|
||||
|
||||
// Defines the default allocator accessor.
|
||||
Allocator* default_allocator();
|
||||
|
||||
// Set the default allocator, used for all dynamic allocation inside ozz.
|
||||
// Returns current memory allocator, such that in can be restored if needed.
|
||||
Allocator* SetDefaulAllocator(Allocator* _allocator);
|
||||
|
||||
// Defines an abstract allocator class.
|
||||
// Implements helper methods to allocate/deallocate POD typed objects instead of
|
||||
// raw memory.
|
||||
// Implements New and Delete function to allocate C++ objects, as a replacement
|
||||
// of new and delete operators.
|
||||
class Allocator {
|
||||
public:
|
||||
// Default virtual destructor.
|
||||
virtual ~Allocator() {}
|
||||
|
||||
// Next functions are the pure virtual functions that must be implemented by
|
||||
// allocator concrete classes.
|
||||
|
||||
// Allocates _size bytes on the specified _alignment boundaries.
|
||||
// Allocate function conforms with standard malloc function specifications.
|
||||
virtual void* Allocate(size_t _size, size_t _alignment) = 0;
|
||||
|
||||
// Frees a block that was allocated with Allocate or Reallocate.
|
||||
// Argument _block can be nullptr.
|
||||
// Deallocate function conforms with standard free function specifications.
|
||||
virtual void Deallocate(void* _block) = 0;
|
||||
};
|
||||
} // namespace memory
|
||||
|
||||
// ozz replacement for c++ operator new with, used to allocate with an
|
||||
// ozz::memory::Allocator. Delete must be used to deallocate such object.
|
||||
// It can be used for constructor with no argument:
|
||||
// Type* object = New<Type>();
|
||||
// or any number of argument:
|
||||
// Type* object = New<Type>(1,2,3,4);
|
||||
template <typename _Ty, typename... _Args>
|
||||
_Ty* New(_Args&&... _args) {
|
||||
void* alloc =
|
||||
memory::default_allocator()->Allocate(sizeof(_Ty), alignof(_Ty));
|
||||
return new (alloc) _Ty(std::forward<_Args>(_args)...);
|
||||
}
|
||||
|
||||
template <typename _Ty>
|
||||
void Delete(_Ty* _object) {
|
||||
if (_object) {
|
||||
// Prevents from false "unreferenced parameter" warning when _Ty has no
|
||||
// explicit destructor.
|
||||
(void)_object;
|
||||
_object->~_Ty();
|
||||
memory::default_allocator()->Deallocate(_object);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_MEMORY_ALLOCATOR_H_
|
||||
@@ -0,0 +1,61 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_MEMORY_UNIQUE_PTR_H_
|
||||
#define OZZ_OZZ_BASE_MEMORY_UNIQUE_PTR_H_
|
||||
|
||||
#include "ozz/base/memory/allocator.h"
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace ozz {
|
||||
|
||||
// Defaut deleter for ozz unique_ptr, uses redirected memory allocator.
|
||||
template <typename _Ty>
|
||||
struct Deleter {
|
||||
Deleter() {}
|
||||
|
||||
template <class _Up>
|
||||
Deleter(const Deleter<_Up>&, _Ty* = nullptr) {}
|
||||
|
||||
void operator()(_Ty* _ptr) const {
|
||||
ozz::Delete(_ptr);
|
||||
}
|
||||
};
|
||||
|
||||
// Defines ozz::unique_ptr to use ozz default deleter.
|
||||
template <typename _Ty, typename _Deleter = ozz::Deleter<_Ty>>
|
||||
using unique_ptr = std::unique_ptr<_Ty, _Deleter>;
|
||||
|
||||
// Implements make_unique to use ozz redirected memory allocator.
|
||||
template <typename _Ty, typename... _Args>
|
||||
unique_ptr<_Ty> make_unique(_Args&&... _args) {
|
||||
return unique_ptr<_Ty>(New<_Ty>(std::forward<_Args>(_args)...));
|
||||
}
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_MEMORY_UNIQUE_PTR_H_
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_PLATFORM_H_
|
||||
#define OZZ_OZZ_BASE_PLATFORM_H_
|
||||
|
||||
// Ensures compiler supports c++11 language standards, to help user understand
|
||||
// compilation error in case it's not supported.
|
||||
// Unfortunately MSVC doesn't update __cplusplus, so test compiler version
|
||||
// instead.
|
||||
#if !((__cplusplus >= 201103L) || (_MSC_VER >= 1900))
|
||||
#error "ozz-animation requires c++11 language standards."
|
||||
#endif // __cplusplus
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
|
||||
namespace ozz {
|
||||
|
||||
// Finds the number of elements of a statically allocated array.
|
||||
#define OZZ_ARRAY_SIZE(_array) (sizeof(_array) / sizeof(_array[0]))
|
||||
|
||||
// Instructs the compiler to try to inline a function, regardless cost/benefit
|
||||
// compiler analysis.
|
||||
// Syntax is: "OZZ_INLINE void function();"
|
||||
#if defined(_MSC_VER)
|
||||
#define OZZ_INLINE __forceinline
|
||||
#else
|
||||
#define OZZ_INLINE inline __attribute__((always_inline))
|
||||
#endif
|
||||
|
||||
// Tells the compiler to never inline a function.
|
||||
// Syntax is: "OZZ_NO_INLINE void function();"
|
||||
#if defined(_MSC_VER)
|
||||
#define OZZ_NOINLINE __declspec(noinline)
|
||||
#else
|
||||
#define OZZ_NOINLINE __attribute__((noinline))
|
||||
#endif
|
||||
|
||||
// Tells the compiler that the memory addressed by the restrict -qualified
|
||||
// pointer is not aliased, aka no other pointer will access that same memory.
|
||||
// Syntax is: void function(int* OZZ_RESTRICT _p);"
|
||||
#define OZZ_RESTRICT __restrict
|
||||
|
||||
// Defines macro to help with DEBUG/NDEBUG syntax.
|
||||
#if defined(NDEBUG)
|
||||
#define OZZ_IF_DEBUG(...)
|
||||
#define OZZ_IF_NDEBUG(...) __VA_ARGS__
|
||||
#else // NDEBUG
|
||||
#define OZZ_IF_DEBUG(...) __VA_ARGS__
|
||||
#define OZZ_IF_NDEBUG(...)
|
||||
#endif // NDEBUG
|
||||
|
||||
// Case sensitive wildcard string matching:
|
||||
// - a ? sign matches any character, except an empty string.
|
||||
// - a * sign matches any string, including an empty string.
|
||||
bool strmatch(const char* _str, const char* _pattern);
|
||||
|
||||
// Tests whether _block is aligned to _alignment boundary.
|
||||
template <typename _Ty>
|
||||
OZZ_INLINE bool IsAligned(_Ty _value, size_t _alignment) {
|
||||
return (_value & (_alignment - 1)) == 0;
|
||||
}
|
||||
template <typename _Ty>
|
||||
OZZ_INLINE bool IsAligned(_Ty* _address, size_t _alignment) {
|
||||
return (reinterpret_cast<uintptr_t>(_address) & (_alignment - 1)) == 0;
|
||||
}
|
||||
|
||||
// Aligns _block address to the first greater address that is aligned to
|
||||
// _alignment boundaries.
|
||||
template <typename _Ty>
|
||||
OZZ_INLINE _Ty Align(_Ty _value, size_t _alignment) {
|
||||
return static_cast<_Ty>(_value + (_alignment - 1)) & (0 - _alignment);
|
||||
}
|
||||
template <typename _Ty>
|
||||
OZZ_INLINE _Ty* Align(_Ty* _address, size_t _alignment) {
|
||||
return reinterpret_cast<_Ty*>(
|
||||
(reinterpret_cast<uintptr_t>(_address) + (_alignment - 1)) &
|
||||
(0 - _alignment));
|
||||
}
|
||||
|
||||
// Offset a pointer from a given number of bytes.
|
||||
template <typename _Ty>
|
||||
_Ty* PointerStride(_Ty* _ty, size_t _stride) {
|
||||
return reinterpret_cast<_Ty*>(reinterpret_cast<uintptr_t>(_ty) + _stride);
|
||||
}
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_PLATFORM_H_
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// 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. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_OZZ_BASE_SPAN_H_
|
||||
#define OZZ_OZZ_BASE_SPAN_H_
|
||||
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
namespace ozz {
|
||||
|
||||
// Defines a range [begin,end[ of objects ot type _Ty.
|
||||
template <typename _Ty>
|
||||
struct span {
|
||||
// Constants and types
|
||||
using element_type = _Ty;
|
||||
using value_type = _Ty;
|
||||
using index_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using pointer = _Ty*;
|
||||
using const_pointer = const _Ty*;
|
||||
using reference = _Ty&;
|
||||
using const_reference = const _Ty&;
|
||||
// Iterators
|
||||
using iterator = pointer;
|
||||
using const_iterator = const_pointer;
|
||||
|
||||
// Default constructor initializes range to empty.
|
||||
span() : data_(nullptr), size_(0) {}
|
||||
|
||||
// Constructs a range from its extreme values.
|
||||
span(_Ty* _begin, _Ty* _end) : data_(_begin), size_(static_cast<size_t>(_end - _begin)) {
|
||||
assert(_begin <= _end && "Invalid range.");
|
||||
}
|
||||
|
||||
// Construct a range from a pointer to a buffer and its size, ie its number of
|
||||
// elements.
|
||||
span(_Ty* _begin, size_t _size) : data_(_begin), size_(_size) {}
|
||||
|
||||
// Copy operator.
|
||||
void operator=(const span& _other) {
|
||||
data_ = _other.data_;
|
||||
size_ = _other.size_;
|
||||
}
|
||||
|
||||
// Construct a range from a single element.
|
||||
explicit span(_Ty& _element) : data_(&_element), size_(1) {}
|
||||
|
||||
// Construct a range from an array, its size is automatically deduced.
|
||||
// It isn't declared explicit as conversion is free and safe.
|
||||
template <size_t _size>
|
||||
span(_Ty (&_array)[_size]) : data_(_array), size_(_size) {}
|
||||
|
||||
// Reinitialized from an array, its size is automatically deduced.
|
||||
template <size_t _size>
|
||||
void operator=(_Ty (&_array)[_size]) {
|
||||
data_ = _array;
|
||||
size_ = _size;
|
||||
}
|
||||
|
||||
// Implement cast operator to allow conversions to span<const _Ty>.
|
||||
operator span<const _Ty>() const { return span<const _Ty>(data_, size_); }
|
||||
|
||||
// Returns a const reference to element _i of range [begin,end[.
|
||||
_Ty& operator[](size_t _i) const {
|
||||
assert(_i < size_ && "Index out of range.");
|
||||
return data_[_i];
|
||||
}
|
||||
|
||||
bool empty() const { return size_ == 0; }
|
||||
|
||||
// Complies with other contiguous containers.
|
||||
_Ty* data() const { return data_; }
|
||||
|
||||
// Gets the number of elements of the range.
|
||||
// This size isn't stored but computed from begin and end pointers.
|
||||
size_t size() const { return size_; }
|
||||
|
||||
// Gets the size in byte of the range.
|
||||
size_t size_bytes() const { return size_ * sizeof(element_type); }
|
||||
|
||||
// Iterator support
|
||||
iterator begin() const { return data_; }
|
||||
iterator end() const { return data_ + size_; }
|
||||
|
||||
private:
|
||||
// span begin pointer.
|
||||
_Ty* data_;
|
||||
|
||||
// span end pointer, should never be dereferenced.
|
||||
size_t size_;
|
||||
};
|
||||
|
||||
// Returns a span from an array.
|
||||
template <typename _Ty, size_t _Size>
|
||||
inline span<_Ty> make_span(_Ty (&_arr)[_Size]) {
|
||||
return {_arr};
|
||||
}
|
||||
|
||||
// Returns a mutable span from a container.
|
||||
template <typename _Container>
|
||||
inline span<typename _Container::value_type> make_span(_Container& _container) {
|
||||
return {_container.data(), _container.size()};
|
||||
}
|
||||
|
||||
// Returns a non mutable span from a container.
|
||||
template <typename _Container>
|
||||
inline span<const typename _Container::value_type> make_span(
|
||||
const _Container& _container) {
|
||||
return {_container.data(), _container.size()};
|
||||
}
|
||||
|
||||
// As bytes
|
||||
template <typename _Ty>
|
||||
inline span<const char> as_bytes(const span<_Ty>& _span) {
|
||||
return {reinterpret_cast<const char*>(_span.data()), _span.size_bytes()};
|
||||
}
|
||||
|
||||
template <typename _Ty>
|
||||
inline span<char> as_writable_bytes(const span<_Ty>& _span) {
|
||||
// Compilation will fail here if _Ty is const. This prevents from writing to
|
||||
// const data.
|
||||
return {reinterpret_cast<char*>(_span.data()), _span.size_bytes()};
|
||||
}
|
||||
|
||||
template <>
|
||||
inline span<const char> as_bytes(const span<char>& _span) {
|
||||
return _span;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline span<char> as_writable_bytes(const span<char>& _span) {
|
||||
return _span;
|
||||
}
|
||||
|
||||
// Fills a typed span from a byte source span. Source byte span is modified to
|
||||
// reflect remain size.
|
||||
template <typename _Ty>
|
||||
inline span<_Ty> fill_span(span<char>& _src, size_t _count) {
|
||||
assert(ozz::IsAligned(_src.data(), alignof(_Ty)) && "Invalid alignment.");
|
||||
const span<_Ty> ret = {reinterpret_cast<_Ty*>(_src.data()), _count};
|
||||
// Validity assertion is done by span constructor.
|
||||
_src = {reinterpret_cast<char*>(ret.end()), _src.end()};
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace ozz
|
||||
#endif // OZZ_OZZ_BASE_SPAN_H_
|
||||
Reference in New Issue
Block a user