/* * Copyright (C) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef API_BASE_MATH_VECTOR_UTIL_H #define API_BASE_MATH_VECTOR_UTIL_H #include #include #include BASE_BEGIN_NAMESPACE() namespace Math { /** \addtogroup group_math_vectorutil * @{ */ // Vector2 /** Dot product of two vector2's */ static inline constexpr float Dot(const Vec2& lhs, const Vec2& rhs) { return (lhs.x * rhs.x) + (lhs.y * rhs.y); } /** Cross product of two vector2's */ static inline constexpr float Cross(const Vec2& lhs, const Vec2& rhs) { return lhs.x * rhs.y - lhs.y * rhs.x; } /** Linearly interpolate between two vector2's */ static inline constexpr Vec2 Lerp(Vec2 v1, Vec2 v2, float t) { t = Math::clamp01(t); return Vec2(v1.x + (v2.x - v1.x) * t, v1.y + (v2.y - v1.y) * t); } /** Return squared magnitude of two vector2's */ static inline constexpr float SqrMagnitude(const Vec2& vec) { return vec.x * vec.x + vec.y * vec.y; } /** Return magnitude of two vector2's */ static inline float Magnitude(const Vec2& vec) { return Math::sqrt(vec.x * vec.x + vec.y * vec.y); } /** Return distance between vector2's */ static inline float distance(const Vec2& v0, const Vec2& v1) { return Magnitude(v1 - v0); } /** Return two component min of vector2's */ static constexpr inline Vec2 min(const Vec2& lhs, const Vec2& rhs) { return Vec2(min(lhs.x, rhs.x), min(lhs.y, rhs.y)); } /** Return two component max of vector2's */ static constexpr inline Vec2 max(const Vec2& lhs, const Vec2& rhs) { return Vec2(max(lhs.x, rhs.x), max(lhs.y, rhs.y)); } /** Return normalized vector2 (if magnitude is not larger than epsilon, returns zero vector) */ static inline Vec2 Normalize(const Vec2& value) { const float mag = Magnitude(value); if (mag > Math::EPSILON) return value / mag; else return Vec2(0.0f, 0.0f); } /** Return vector2 perpendicular to input in clock-wise direction */ static inline Vec2 PerpendicularCW(const Vec2& value) { return Vec2(-value.y, value.x); } /** Return vector2 perpendicular to input in counter clock-wise direction */ static inline Vec2 PerpendicularCCW(const Vec2& value) { return Vec2(value.y, -value.x); } /** Return vector2 rotated clock wise by angle radians */ static inline Vec2 RotateCW(const Vec2& value, float angle) { const float s = Math::sin(angle); const float c = Math::cos(angle); return Vec2(value.x * c - value.y * s, value.y * c + value.x * s); } /** Return intersection of two Vec2 start points and direction vectors. Returns boolean flag indicating if the vectors * intersect. */ static inline Vec2 Intersect( const Vec2& aStart, const Vec2& aDir, const Vec2& bStart, const Vec2& bDir, bool infinite, bool& intersected) { const auto denominator = Cross(aDir, bDir); if (Math::abs(denominator) < BASE_EPSILON) { // The lines are parallel intersected = false; return {}; } // Solve the intersection positions const auto originDist = bStart - aStart; const auto uNumerator = Cross(originDist, aDir); const auto u = uNumerator / denominator; const auto t = Cross(originDist, bDir) / denominator; if (!infinite && (t < 0 || t > 1 || u < 0 || u > 1)) { // The intersection lies outside of the line segments intersected = false; return {}; } intersected = true; // Calculate the intersection point return aStart + aDir * t; } // Vector3 /** Dot product of two vector3's */ static inline constexpr float Dot(const Vec3& lhs, const Vec3& rhs) { return (lhs.x * rhs.x) + (lhs.y * rhs.y) + (lhs.z * rhs.z); } /** Cross product of two vector3's */ static inline constexpr Vec3 Cross(const Vec3& lhs, const Vec3& rhs) { return Vec3(lhs.y * rhs.z - lhs.z * rhs.y, lhs.z * rhs.x - lhs.x * rhs.z, lhs.x * rhs.y - lhs.y * rhs.x); } /** Linearly interpolate between v1 and v2 vector3's by value t */ static inline constexpr Vec3 Lerp(const Vec3& v1, const Vec3& v2, float t) { t = Math::clamp01(t); return Vec3(v1.x + (v2.x - v1.x) * t, v1.y + (v2.y - v1.y) * t, v1.z + (v2.z - v1.z) * t); } /** Return squared magnitude of vector3's */ static inline constexpr float SqrMagnitude(const Vec3& vec) { return vec.x * vec.x + vec.y * vec.y + vec.z * vec.z; } /** Return magnitude of vector3's */ static inline float Magnitude(const Vec3& vec) { return Math::sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z); } /** Return squared distance of two vector3's */ static inline float Distance2(const Vec3& v0, const Vec3& v1) { return SqrMagnitude(v1 - v0); } /** Return normalized vector3 (if magnitude is not larger than epsilon, returns zero vector) */ static inline Vec3 Normalize(const Vec3& value) { const float mag = Magnitude(value); if (mag > Math::EPSILON) { return value / mag; } else { return Vec3(0.0f, 0.0f, 0.0f); } } /** Return three component min of vector3's */ static constexpr inline Vec3 min(const Vec3& lhs, const Vec3& rhs) { return Vec3(min(lhs.x, rhs.x), min(lhs.y, rhs.y), min(lhs.z, rhs.z)); } /** Return three component max of vector3's */ static constexpr inline Vec3 max(const Vec3& lhs, const Vec3& rhs) { return Vec3(max(lhs.x, rhs.x), max(lhs.y, rhs.y), max(lhs.z, rhs.z)); } /** Return scaled value of vector3 */ static inline Vec3 Scale(Vec3 const& v, float desiredLength) { return v * desiredLength / Magnitude(v); } /** Combine vector3's which have been multiplied with scalar (a * ascl) + (b * bscl) */ static inline constexpr Vec3 Combine(Vec3 const& a, Vec3 const& b, float ascl, float bscl) { return (a * ascl) + (b * bscl); } // Vector4 /** Return squared magnitude of vector4 */ static inline constexpr float SqrMagnitude(const Vec4& vec) { return vec.x * vec.x + vec.y * vec.y + vec.z * vec.z + vec.w * vec.w; } /** Linearly interpolate between v1 and v2 vector4's by value t */ static inline constexpr Vec4 Lerp(const Vec4& v1, const Vec4& v2, float t) { t = Math::clamp01(t); return Vec4(v1.x + (v2.x - v1.x) * t, v1.y + (v2.y - v1.y) * t, v1.z + (v2.z - v1.z) * t, v1.w + (v2.w - v1.w) * t); } /** @} */ } // namespace Math BASE_END_NAMESPACE() #endif // API_BASE_MATH_VECTOR_UTIL_H