#pragma once //////////////////////////////////////////////////////////////////////////////// // The MIT License (MIT) // // Copyright (c) 2020 Nicholas Frechette & Animation Compression Library contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. //////////////////////////////////////////////////////////////////////////////// #include "acl/core/bitset.h" #include "acl/core/compressed_tracks.h" #include "acl/core/compressed_tracks_version.h" #include "acl/core/range_reduction_types.h" #include "acl/core/track_formats.h" #include "acl/core/impl/compiler_utils.h" #include ACL_IMPL_FILE_PRAGMA_PUSH namespace acl { namespace acl_impl { struct alignas(64) persistent_transform_decompression_context_v0 { // Clip related data // offsets // Only member used to detect if we are initialized, must be first const compressed_tracks* tracks; // 0 | 0 const uint32_t* constant_tracks_bitset; // 4 | 8 const uint8_t* constant_track_data; // 8 | 16 const uint32_t* default_tracks_bitset; // 12 | 24 const uint8_t* clip_range_data; // 16 | 32 float clip_duration; // 20 | 40 bitset_description bitset_desc; // 24 | 44 uint32_t clip_hash; // 28 | 48 rotation_format8 rotation_format; // 32 | 52 vector_format8 translation_format; // 33 | 53 vector_format8 scale_format; // 34 | 54 range_reduction_flags8 range_reduction; // 35 | 55 uint8_t num_rotation_components; // 36 | 56 uint8_t has_segments; // 37 | 57 uint8_t padding0[2]; // 38 | 58 // Seeking related data float sample_time; // 40 | 60 const uint8_t* format_per_track_data[2]; // 44 | 64 const uint8_t* segment_range_data[2]; // 52 | 80 const uint8_t* animated_track_data[2]; // 60 | 96 uint32_t key_frame_bit_offsets[2]; // 68 | 112 float interpolation_alpha; // 76 | 120 uint8_t padding1[sizeof(void*) == 4 ? 48 : 4]; // 80 | 124 // Total size: 128 | 128 ////////////////////////////////////////////////////////////////////////// const compressed_tracks* get_compressed_tracks() const { return tracks; } compressed_tracks_version16 get_version() const { return tracks->get_version(); } bool is_initialized() const { return tracks != nullptr; } void reset() { tracks = nullptr; } }; static_assert(sizeof(persistent_transform_decompression_context_v0) == 128, "Unexpected size"); // We use adapters to wrap the decompression_settings // This allows us to re-use the code for skipping and decompressing Vector3 samples // Code generation will generate specialized code for each specialization template struct translation_decompression_settings_adapter { // Forward to our decompression settings static constexpr range_reduction_flags8 get_range_reduction_flag() { return range_reduction_flags8::translations; } static constexpr vector_format8 get_vector_format(const persistent_transform_decompression_context_v0& context) { return context.translation_format; } static constexpr bool is_vector_format_supported(vector_format8 format) { return decompression_settings_type::is_translation_format_supported(format); } }; template struct scale_decompression_settings_adapter { // Forward to our decompression settings static constexpr range_reduction_flags8 get_range_reduction_flag() { return range_reduction_flags8::scales; } static constexpr vector_format8 get_vector_format(const persistent_transform_decompression_context_v0& context) { return context.scale_format; } static constexpr bool is_vector_format_supported(vector_format8 format) { return decompression_settings_type::is_scale_format_supported(format); } }; // Returns the statically known number of rotation formats supported by the decompression settings template constexpr int32_t num_supported_rotation_formats() { return decompression_settings_type::is_rotation_format_supported(rotation_format8::quatf_full) + decompression_settings_type::is_rotation_format_supported(rotation_format8::quatf_drop_w_full) + decompression_settings_type::is_rotation_format_supported(rotation_format8::quatf_drop_w_variable); } // Returns the statically known rotation format supported if we only support one, otherwise we return the input value // which might not be known statically template constexpr rotation_format8 get_rotation_format(rotation_format8 format) { return num_supported_rotation_formats() > 1 // More than one format is supported, return the input value, whatever it may be ? format // Only one format is supported, figure out statically which one it is and return it : (decompression_settings_type::is_rotation_format_supported(rotation_format8::quatf_full) ? rotation_format8::quatf_full : (decompression_settings_type::is_rotation_format_supported(rotation_format8::quatf_drop_w_full) ? rotation_format8::quatf_drop_w_full : rotation_format8::quatf_drop_w_variable)); } // Returns the statically known number of vector formats supported by the decompression settings template constexpr int32_t num_supported_vector_formats() { return decompression_settings_adapter_type::is_vector_format_supported(vector_format8::vector3f_full) + decompression_settings_adapter_type::is_vector_format_supported(vector_format8::vector3f_variable); } // Returns the statically known vector format supported if we only support one, otherwise we return the input value // which might not be known statically template constexpr vector_format8 get_vector_format(vector_format8 format) { return num_supported_vector_formats() > 1 // More than one format is supported, return the input value, whatever it may be ? format // Only one format is supported, figure out statically which one it is and return it : (decompression_settings_adapter_type::is_vector_format_supported(vector_format8::vector3f_full) ? vector_format8::vector3f_full : vector_format8::vector3f_variable); } } } ACL_IMPL_FILE_PRAGMA_POP