1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "interpolator.h"
17
18#include <base/math/quaternion_util.h>
19
20META_BEGIN_NAMESPACE()
21
22class FloatInterpolator : public Interpolator<float, FloatInterpolator, ClassId::FloatInterpolator> {};
23class DoubleInterpolator : public Interpolator<double, DoubleInterpolator, ClassId::DoubleInterpolator> {};
24class Vec2Interpolator : public Interpolator<BASE_NS::Math::Vec2, Vec2Interpolator, ClassId::Vec2Interpolator> {};
25class Vec3Interpolator : public Interpolator<BASE_NS::Math::Vec3, Vec3Interpolator, ClassId::Vec3Interpolator> {};
26class Vec4Interpolator : public Interpolator<BASE_NS::Math::Vec4, Vec4Interpolator, ClassId::Vec4Interpolator> {};
27class UVec2Interpolator : public Interpolator<BASE_NS::Math::UVec2, UVec2Interpolator, ClassId::UVec2Interpolator> {};
28class IVec2Interpolator : public Interpolator<BASE_NS::Math::IVec2, IVec2Interpolator, ClassId::IVec2Interpolator> {};
29class UInt8Interpolator : public Interpolator<uint8_t, UInt8Interpolator, ClassId::UInt8Interpolator> {};
30class UInt16Interpolator : public Interpolator<uint16_t, UInt16Interpolator, ClassId::UInt16Interpolator> {};
31class UInt32Interpolator : public Interpolator<uint32_t, UInt32Interpolator, ClassId::UInt32Interpolator> {};
32class UInt64Interpolator : public Interpolator<uint64_t, UInt64Interpolator, ClassId::UInt64Interpolator> {};
33class Int8Interpolator : public Interpolator<int8_t, Int8Interpolator, ClassId::Int8Interpolator> {};
34class Int16Interpolator : public Interpolator<int16_t, Int16Interpolator, ClassId::Int16Interpolator> {};
35class Int32Interpolator : public Interpolator<int32_t, Int32Interpolator, ClassId::Int32Interpolator> {};
36class Int64Interpolator : public Interpolator<int64_t, Int64Interpolator, ClassId::Int64Interpolator> {};
37
38class QuatInterpolator : public META_NS::BaseObjectFwd<QuatInterpolator, ClassId::QuatInterpolator,
39                             META_NS::ClassId::BaseObject, IInterpolator> {
40    using Type = BASE_NS::Math::Quat;
41    AnyReturnValue Interpolate(IAny& output, const IAny& from, const IAny& to, float t) const override
42    {
43        if (IsSetCompatibleWith<Type>(output) && IsGetCompatibleWith<Type>(from) && IsGetCompatibleWith<Type>(to)) {
44            Type value0 = GetValue<Type>(from);
45            Type value1 = GetValue<Type>(to);
46            return output.SetValue<Type>(BASE_NS::Math::Slerp(value0, value1, t));
47        }
48        return AnyReturn::INCOMPATIBLE_TYPE;
49    }
50
51    bool IsCompatibleWith(TypeId id) const noexcept override
52    {
53        return id == UidFromType<Type>();
54    }
55};
56
57class DefaultInterpolator : public META_NS::BaseObjectFwd<DefaultInterpolator, ClassId::DefaultInterpolator,
58                                META_NS::ClassId::BaseObject, IInterpolator> {
59    AnyReturnValue Interpolate(IAny& output, const IAny& from, const IAny& to, float t) const override
60    {
61        // The default interpolator doesn't know how to interpolate, so we just set the property value to either
62        // from or to based on t
63        if (t > .5f) {
64            return output.CopyFrom(to);
65        }
66        return output.CopyFrom(from);
67    }
68    bool IsCompatibleWith(TypeId id) const noexcept override
69    {
70        // Default interpolator is compatible with any type
71        return true;
72    }
73};
74
75// No math operations have been defined for integer type vec3/4, implement interpolators manually
76class UVec3Interpolator : public META_NS::BaseObjectFwd<UVec3Interpolator, ClassId::UVec3Interpolator,
77                              META_NS::ClassId::BaseObject, IInterpolator> {
78    using Type = BASE_NS::Math::UVec3;
79    AnyReturnValue Interpolate(IAny& output, const IAny& from, const IAny& to, float t) const override
80    {
81        if (IsSetCompatibleWith<Type>(output) && IsGetCompatibleWith<Type>(from) && IsGetCompatibleWith<Type>(to)) {
82            Type value0 = GetValue<Type>(from);
83            Type value1 = GetValue<Type>(to);
84            Type value;
85            value.x = value0.x + (value1.x - value0.x) * t;
86            value.y = value0.y + (value1.y - value0.y) * t;
87            value.z = value0.z + (value1.z - value0.z) * t;
88            return output.SetValue<Type>(value);
89        }
90        return AnyReturn::INCOMPATIBLE_TYPE;
91    }
92    bool IsCompatibleWith(TypeId id) const noexcept override
93    {
94        return id == UidFromType<Type>();
95    }
96};
97
98class UVec4Interpolator : public META_NS::BaseObjectFwd<UVec4Interpolator, ClassId::UVec4Interpolator,
99                              META_NS::ClassId::BaseObject, IInterpolator> {
100    using Type = BASE_NS::Math::UVec4;
101    AnyReturnValue Interpolate(IAny& output, const IAny& from, const IAny& to, float t) const override
102    {
103        if (IsSetCompatibleWith<Type>(output) && IsGetCompatibleWith<Type>(from) && IsGetCompatibleWith<Type>(to)) {
104            Type value0 = GetValue<Type>(from);
105            Type value1 = GetValue<Type>(to);
106            Type value;
107            value.x = value0.x + (value1.x - value0.x) * t;
108            value.y = value0.y + (value1.y - value0.y) * t;
109            value.z = value0.z + (value1.z - value0.z) * t;
110            value.w = value0.w + (value1.w - value0.w) * t;
111            return output.SetValue<Type>(value);
112        }
113        return AnyReturn::INCOMPATIBLE_TYPE;
114    }
115    bool IsCompatibleWith(TypeId id) const noexcept override
116    {
117        return id == UidFromType<Type>();
118    }
119};
120
121class IVec3Interpolator : public META_NS::BaseObjectFwd<IVec3Interpolator, ClassId::IVec3Interpolator,
122                              META_NS::ClassId::BaseObject, IInterpolator> {
123    using Type = BASE_NS::Math::IVec3;
124    AnyReturnValue Interpolate(IAny& output, const IAny& from, const IAny& to, float t) const override
125    {
126        if (IsSetCompatibleWith<Type>(output) && IsGetCompatibleWith<Type>(from) && IsGetCompatibleWith<Type>(to)) {
127            Type value0 = GetValue<Type>(from);
128            Type value1 = GetValue<Type>(to);
129            Type value;
130            value.x = value0.x + (value1.x - value0.x) * t;
131            value.y = value0.y + (value1.y - value0.y) * t;
132            value.z = value0.z + (value1.z - value0.z) * t;
133            return output.SetValue<Type>(value);
134        }
135        return AnyReturn::INCOMPATIBLE_TYPE;
136    }
137    bool IsCompatibleWith(TypeId id) const noexcept override
138    {
139        return id == UidFromType<Type>();
140    }
141};
142class IVec4Interpolator : public META_NS::BaseObjectFwd<IVec4Interpolator, ClassId::IVec4Interpolator,
143                              META_NS::ClassId::BaseObject, IInterpolator> {
144    using Type = BASE_NS::Math::IVec4;
145    AnyReturnValue Interpolate(IAny& output, const IAny& from, const IAny& to, float t) const override
146    {
147        if (IsSetCompatibleWith<Type>(output) && IsGetCompatibleWith<Type>(from) && IsGetCompatibleWith<Type>(to)) {
148            Type value0 = GetValue<Type>(from);
149            Type value1 = GetValue<Type>(to);
150            Type value;
151            value.x = value0.x + (value1.x - value0.x) * t;
152            value.y = value0.y + (value1.y - value0.y) * t;
153            value.z = value0.z + (value1.z - value0.z) * t;
154            value.w = value0.w + (value1.w - value0.w) * t;
155            return output.SetValue<Type>(value);
156        }
157        return AnyReturn::INCOMPATIBLE_TYPE;
158    }
159    bool IsCompatibleWith(TypeId id) const noexcept override
160    {
161        return id == UidFromType<Type>();
162    }
163};
164
165namespace BuiltInInterpolators {
166
167struct InterpolatorInfo {
168    ObjectTypeInfo OBJECT_INFO;
169    TypeId propertyTypeUid;
170    ObjectId interpolatorClassUid;
171};
172
173static constexpr InterpolatorInfo BUILT_IN_INTERPOLATOR_INFO[] = {
174    { FloatInterpolator::OBJECT_INFO, UidFromType<float>(), ClassId::FloatInterpolator },
175    { DoubleInterpolator::OBJECT_INFO, UidFromType<double>(), ClassId::DoubleInterpolator },
176    { Vec2Interpolator::OBJECT_INFO, UidFromType<BASE_NS::Math::Vec2>(), ClassId::Vec2Interpolator },
177    { Vec3Interpolator::OBJECT_INFO, UidFromType<BASE_NS::Math::Vec3>(), ClassId::Vec3Interpolator },
178    { Vec4Interpolator::OBJECT_INFO, UidFromType<BASE_NS::Math::Vec4>(), ClassId::Vec4Interpolator },
179    { UVec2Interpolator::OBJECT_INFO, UidFromType<BASE_NS::Math::UVec2>(), ClassId::UVec2Interpolator },
180    { UVec3Interpolator::OBJECT_INFO, UidFromType<BASE_NS::Math::UVec3>(), ClassId::UVec3Interpolator },
181    { UVec4Interpolator::OBJECT_INFO, UidFromType<BASE_NS::Math::UVec4>(), ClassId::UVec4Interpolator },
182    { IVec2Interpolator::OBJECT_INFO, UidFromType<BASE_NS::Math::IVec2>(), ClassId::IVec2Interpolator },
183    { IVec3Interpolator::OBJECT_INFO, UidFromType<BASE_NS::Math::IVec3>(), ClassId::IVec3Interpolator },
184    { IVec4Interpolator::OBJECT_INFO, UidFromType<BASE_NS::Math::IVec4>(), ClassId::IVec4Interpolator },
185    { UInt8Interpolator::OBJECT_INFO, UidFromType<uint8_t>(), ClassId::UInt8Interpolator },
186    { UInt16Interpolator::OBJECT_INFO, UidFromType<uint16_t>(), ClassId::UInt16Interpolator },
187    { UInt32Interpolator::OBJECT_INFO, UidFromType<uint32_t>(), ClassId::UInt32Interpolator },
188    { UInt64Interpolator::OBJECT_INFO, UidFromType<uint64_t>(), ClassId::UInt64Interpolator },
189    { Int8Interpolator::OBJECT_INFO, UidFromType<int8_t>(), ClassId::Int8Interpolator },
190    { Int16Interpolator::OBJECT_INFO, UidFromType<int16_t>(), ClassId::Int16Interpolator },
191    { Int32Interpolator::OBJECT_INFO, UidFromType<int32_t>(), ClassId::Int32Interpolator },
192    { Int64Interpolator::OBJECT_INFO, UidFromType<int64_t>(), ClassId::Int64Interpolator },
193    { QuatInterpolator::OBJECT_INFO, UidFromType<BASE_NS::Math::Quat>(), ClassId::QuatInterpolator },
194};
195
196} // namespace BuiltInInterpolators
197
198void RegisterDefaultInterpolators(IObjectRegistry& registry)
199{
200    for (const auto& info : BuiltInInterpolators::BUILT_IN_INTERPOLATOR_INFO) {
201        // Register the classes themselves
202        registry.RegisterObjectType(info.OBJECT_INFO.GetFactory());
203        // Then register them as interpolators (note that default interpolator doesn't need to be registered)
204        registry.RegisterInterpolator(info.propertyTypeUid, info.interpolatorClassUid.ToUid());
205    }
206
207    // No need to register the default interpolator, only register the class
208    registry.RegisterObjectType<DefaultInterpolator>();
209}
210void UnRegisterDefaultInterpolators(IObjectRegistry& registry)
211{
212    for (const auto& info : BuiltInInterpolators::BUILT_IN_INTERPOLATOR_INFO) {
213        // Unregister interpolator
214        registry.UnregisterInterpolator(info.propertyTypeUid);
215        // Unregister object
216        registry.UnregisterObjectType(info.OBJECT_INFO.GetFactory());
217    }
218    // Unregister default interpolator
219    registry.UnregisterObjectType<DefaultInterpolator>();
220}
221
222META_END_NAMESPACE()
223