Changeset View
Changeset View
Standalone View
Standalone View
extern/gltf-draco/draco/src/draco/core/vector_d.h
- This file was added.
| // Copyright 2016 The Draco Authors. | |||||
| // | |||||
| // 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 DRACO_CORE_VECTOR_D_H_ | |||||
| #define DRACO_CORE_VECTOR_D_H_ | |||||
| #include <inttypes.h> | |||||
| #include <algorithm> | |||||
| #include <array> | |||||
| #include <cmath> | |||||
| #include "draco/core/macros.h" | |||||
| namespace draco { | |||||
| // D-dimensional vector class with basic operations. | |||||
| template <class CoeffT, int dimension_t> | |||||
| class VectorD { | |||||
| public: | |||||
| typedef VectorD<CoeffT, dimension_t> Self; | |||||
| typedef CoeffT CoefficientType; | |||||
| static constexpr int dimension = dimension_t; | |||||
| VectorD() { | |||||
| for (int i = 0; i < dimension_t; ++i) | |||||
| (*this)[i] = CoeffT(0); | |||||
| } | |||||
| // The following constructor does not compile in opt mode, which for now led | |||||
| // to the constructors further down, which is not ideal. | |||||
| // TODO(hemmer): fix constructor below and remove others. | |||||
| // template <typename... Args> | |||||
| // explicit VectorD(Args... args) : v_({args...}) {} | |||||
| VectorD(const CoeffT &c0, const CoeffT &c1) : v_({{c0, c1}}) { | |||||
| DRACO_DCHECK_EQ(dimension_t, 2); | |||||
| v_[0] = c0; | |||||
| v_[1] = c1; | |||||
| } | |||||
| VectorD(const CoeffT &c0, const CoeffT &c1, const CoeffT &c2) | |||||
| : v_({{c0, c1, c2}}) { | |||||
| DRACO_DCHECK_EQ(dimension_t, 3); | |||||
| } | |||||
| VectorD(const CoeffT &c0, const CoeffT &c1, const CoeffT &c2, | |||||
| const CoeffT &c3) | |||||
| : v_({{c0, c1, c2, c3}}) { | |||||
| DRACO_DCHECK_EQ(dimension_t, 4); | |||||
| } | |||||
| VectorD(const CoeffT &c0, const CoeffT &c1, const CoeffT &c2, | |||||
| const CoeffT &c3, const CoeffT &c4) | |||||
| : v_({{c0, c1, c2, c3, c4}}) { | |||||
| DRACO_DCHECK_EQ(dimension_t, 5); | |||||
| } | |||||
| VectorD(const CoeffT &c0, const CoeffT &c1, const CoeffT &c2, | |||||
| const CoeffT &c3, const CoeffT &c4, const CoeffT &c5) | |||||
| : v_({{c0, c1, c2, c3, c4, c5}}) { | |||||
| DRACO_DCHECK_EQ(dimension_t, 6); | |||||
| } | |||||
| VectorD(const CoeffT &c0, const CoeffT &c1, const CoeffT &c2, | |||||
| const CoeffT &c3, const CoeffT &c4, const CoeffT &c5, | |||||
| const CoeffT &c6) | |||||
| : v_({{c0, c1, c2, c3, c4, c5, c6}}) { | |||||
| DRACO_DCHECK_EQ(dimension_t, 7); | |||||
| } | |||||
| VectorD(const Self &o) { | |||||
| for (int i = 0; i < dimension_t; ++i) | |||||
| (*this)[i] = o[i]; | |||||
| } | |||||
| CoeffT &operator[](int i) { return v_[i]; } | |||||
| const CoeffT &operator[](int i) const { return v_[i]; } | |||||
| // TODO(hemmer): remove. | |||||
| // Similar to interface of Eigen library. | |||||
| CoeffT &operator()(int i) { return v_[i]; } | |||||
| const CoeffT &operator()(int i) const { return v_[i]; } | |||||
| // Unary operators. | |||||
| Self operator-() const { | |||||
| Self ret; | |||||
| for (int i = 0; i < dimension_t; ++i) { | |||||
| ret[i] = -(*this)[i]; | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| // Binary operators. | |||||
| Self operator+(const Self &o) const { | |||||
| Self ret; | |||||
| for (int i = 0; i < dimension_t; ++i) { | |||||
| ret[i] = (*this)[i] + o[i]; | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| Self operator-(const Self &o) const { | |||||
| Self ret; | |||||
| for (int i = 0; i < dimension_t; ++i) { | |||||
| ret[i] = (*this)[i] - o[i]; | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| Self operator*(const CoeffT &o) const { | |||||
| Self ret; | |||||
| for (int i = 0; i < dimension_t; ++i) { | |||||
| ret[i] = (*this)[i] * o; | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| Self operator/(const CoeffT &o) const { | |||||
| Self ret; | |||||
| for (int i = 0; i < dimension_t; ++i) { | |||||
| ret[i] = (*this)[i] / o; | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| bool operator==(const Self &o) const { | |||||
| for (int i = 0; i < dimension_t; ++i) { | |||||
| if ((*this)[i] != o[i]) | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| bool operator!=(const Self &x) const { return !((*this) == x); } | |||||
| bool operator<(const Self &x) const { | |||||
| for (int i = 0; i < dimension_t - 1; ++i) { | |||||
| if (v_[i] < x.v_[i]) | |||||
| return true; | |||||
| if (v_[i] > x.v_[i]) | |||||
| return false; | |||||
| } | |||||
| // Only one check needed for the last dimension. | |||||
| if (v_[dimension_t - 1] < x.v_[dimension_t - 1]) | |||||
| return true; | |||||
| return false; | |||||
| } | |||||
| // Functions. | |||||
| CoeffT SquaredNorm() const { return this->Dot(*this); } | |||||
| // Computes L1, the sum of absolute values of all entries. | |||||
| CoeffT AbsSum() const { | |||||
| CoeffT result(0); | |||||
| for (int i = 0; i < dimension_t; ++i) { | |||||
| result += std::abs(v_[i]); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| CoeffT Dot(const Self &o) const { | |||||
| CoeffT ret(0); | |||||
| for (int i = 0; i < dimension_t; ++i) { | |||||
| ret += (*this)[i] * o[i]; | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| void Normalize() { | |||||
| const CoeffT magnitude = std::sqrt(this->SquaredNorm()); | |||||
| if (magnitude == 0) { | |||||
| return; | |||||
| } | |||||
| for (int i = 0; i < dimension_t; ++i) { | |||||
| (*this)[i] /= magnitude; | |||||
| } | |||||
| } | |||||
| CoeffT *data() { return &(v_[0]); } | |||||
| private: | |||||
| std::array<CoeffT, dimension_t> v_; | |||||
| }; | |||||
| // Scalar multiplication from the other side too. | |||||
| template <class CoeffT, int dimension_t> | |||||
| VectorD<CoeffT, dimension_t> operator*(const CoeffT &o, | |||||
| const VectorD<CoeffT, dimension_t> &v) { | |||||
| return v * o; | |||||
| } | |||||
| // Calculates the squared distance between two points. | |||||
| template <class CoeffT, int dimension_t> | |||||
| CoeffT SquaredDistance(const VectorD<CoeffT, dimension_t> &v1, | |||||
| const VectorD<CoeffT, dimension_t> &v2) { | |||||
| CoeffT difference; | |||||
| CoeffT squared_distance = 0; | |||||
| // Check each index separately so difference is never negative and underflow | |||||
| // is avoided for unsigned types. | |||||
| for (int i = 0; i < dimension_t; ++i) { | |||||
| if (v1[i] >= v2[i]) { | |||||
| difference = v1[i] - v2[i]; | |||||
| } else { | |||||
| difference = v2[i] - v1[i]; | |||||
| } | |||||
| squared_distance += (difference * difference); | |||||
| } | |||||
| return squared_distance; | |||||
| } | |||||
| // Global function computing the cross product of two 3D vectors. | |||||
| template <class CoeffT> | |||||
| VectorD<CoeffT, 3> CrossProduct(const VectorD<CoeffT, 3> &u, | |||||
| const VectorD<CoeffT, 3> &v) { | |||||
| // Preventing accidental use with uint32_t and the like. | |||||
| static_assert(std::is_signed<CoeffT>::value, | |||||
| "CoeffT must be a signed type. "); | |||||
| VectorD<CoeffT, 3> r; | |||||
| r[0] = (u[1] * v[2]) - (u[2] * v[1]); | |||||
| r[1] = (u[2] * v[0]) - (u[0] * v[2]); | |||||
| r[2] = (u[0] * v[1]) - (u[1] * v[0]); | |||||
| return r; | |||||
| } | |||||
| template <class CoeffT, int dimension_t> | |||||
| inline std::ostream &operator<<( | |||||
| std::ostream &out, const draco::VectorD<CoeffT, dimension_t> &vec) { | |||||
| for (int i = 0; i < dimension_t - 1; ++i) { | |||||
| out << vec[i] << " "; | |||||
| } | |||||
| out << vec[dimension_t - 1]; | |||||
| return out; | |||||
| } | |||||
| typedef VectorD<float, 2> Vector2f; | |||||
| typedef VectorD<float, 3> Vector3f; | |||||
| typedef VectorD<float, 4> Vector4f; | |||||
| typedef VectorD<float, 5> Vector5f; | |||||
| typedef VectorD<float, 6> Vector6f; | |||||
| typedef VectorD<float, 7> Vector7f; | |||||
| typedef VectorD<uint32_t, 2> Vector2ui; | |||||
| typedef VectorD<uint32_t, 3> Vector3ui; | |||||
| typedef VectorD<uint32_t, 4> Vector4ui; | |||||
| typedef VectorD<uint32_t, 5> Vector5ui; | |||||
| typedef VectorD<uint32_t, 6> Vector6ui; | |||||
| typedef VectorD<uint32_t, 7> Vector7ui; | |||||
| } // namespace draco | |||||
| #endif // DRACO_CORE_VECTOR_D_H_ | |||||