Preamble
With the global popularity of Unity technology, the ease of use of its API has been favored by more and more developers.
Based on D Ziyu 's work, this article imitates Unity's class structure and expands it into a C++ class template.
In order to be more convenient to use in other C++ projects.
Source code address: https://github.com/duzixi/XYZ
First blog post: https://www.csdn.net/duzixi
source code
Vector3.h
// // Vector3.h // XYZ // C++ implementation of common class templates for 3D space. It encapsulates the common members and methods of three-dimensional space vectors. // // Created by 杜子兮(duzixi[at]gmail[dot]com) on 18-4-7. // Copyright (c) 2018年 www.duzixi.com All rights reserved. // #pragma once using namespace std; namespace XYZ { template <class T> class Vector3 { public: T x; T y; T z; // Constructor =============================== Vector3(); Vector3(T _x, T _y); Vector3(T _x, T _y, T _z); // destructor ~Vector3(); // Properties ======================================= // common vector /* This class uses the following coordinate system: and ^ | | Top view z-axis vertical screen facing up | o-----------> x */ // (0, -1, 0) static Vector3<T> back; // (0, 0, -1) static Vector3<T> down; // (0, 1, 0) static Vector3<T> forward; // (0, 1, 0) static Vector3<T> fwd; // (-1, 0, 0) static Vector3<T> left; // (1, 1, 1) static Vector3<T> one; // (1, 0, 0) static Vector3<T> right; // (0, 0, 1) static Vector3<T> up; // (0, 0, 0) static Vector3<T> zero; // modulo square T sqrMagnitude; // modulo T magnitude; // class method ================================= // dot multiply static T Dot(Vector3<T> lhs, Vector3<T> rhs); // cross product static Vector3<T> Cross(Vector3<T> lhs, Vector3<T> rhs); // distance static T Distance(Vector3<T> a, Vector3<T> b); // Unitization static Vector3<T> Normalize(Vector3<T> value); // The size of the included angle (angle) static T Angle(Vector3<T> from, Vector3<T> to); // Angle size (radians) static T AngleBetween(Vector3<T> from, Vector3<T> to); // Maximum value (X, Y, Z are the maximum) static Vector3<T> Max(Vector3<T> lhs, Vector3<T> rhs); // Minimum value (X, Y, Z are the minimum) static Vector3<T> Min(Vector3<T> lhs, Vector3<T> rhs); // vector projection static Vector3<T> Project(Vector3<T> vector, Vector3<T> onNormal); // zoom static Vector3<T> Scale(Vector3<T> a, Vector3<T> b); // member method =============================== // normalize (do not change the vector itself) Vector3<T> normalized(); // zoom void Scale(Vector3<T> scale); // set up void Set(T _x, T _y, T _z); // return string string ToString(); // operator overloading =========================== // compare for equality bool operator==(const Vector3<T> &rhs) const; // Compare if they are not equal bool operator!=(const Vector3<T> &rhs) const; }; // operator overloading template <class T> Vector3<T> operator+(const Vector3<T> &a, const Vector3<T> &b); template <class T> Vector3<T> operator-(const Vector3<T> &a, const Vector3<T> &b); template <class T> Vector3<T> operator*(const T d, const Vector3<T> &a); template <class T> Vector3<T> operator* (const Vector3<T> &a, const T d); template <class T> Vector3<T> operator/ (const Vector3<T> &a, const T d); }
Vector3.cpp
// // Vector3.h // XYZ // C++ implementation of common class templates for 3D space. It encapsulates the common members and methods of three-dimensional space vectors. // // Created by 杜子兮(duzixi[at]gmail[dot]com) on 18-4-7. // Copyright (c) 2018年 www.duzixi.com All rights reserved. // #include "stdafx.h" #include "Vector3.h" #ifndef _VECTOR3_CPP__ #define _VECTOR3_CPP__ namespace XYZ { template <class T> Vector3<T>::Vector3() { } template <class T> Vector3<T>::~Vector3() { } template <class T> Vector3<T>::Vector3(T _x, T _y) { x = _x; y = _y; z = 0; sqrMagnitude = x * x + y * y + z * z; magnitude = sqrt(sqrMagnitude); } template <class T> Vector3<T>::Vector3(T _x, T _y, T _z) { x = _x; y = _y; z = _z; sqrMagnitude = x * x + y * y + z * z; magnitude = sqrt(sqrMagnitude); } // (0, -1, 0) template <class T> Vector3<T> Vector3<T>::back = Vector3<T>(0, -1, 0); // (0, 0, -1) template <class T> Vector3<T> Vector3<T>::down = Vector3<T>(0, 0, -1); // (0, 1, 0) template <class T> Vector3<T> Vector3<T>::forward = Vector3<T>(0, 1, 0); // (0, 1, 0) template <class T> Vector3<T> Vector3<T>::fwd = Vector3<T>(0, 1, 0); // (-1, 0, 0) template <class T> Vector3<T> Vector3<T>::left = Vector3<T>(-1, 0, 0); // (1, 1, 1) template <class T> Vector3<T> Vector3<T>::one = Vector3<T>(1, 1, 1); // (1, 0, 0) template <class T> Vector3<T> Vector3<T>::right = Vector3<T>(1, 0, 0); // (0, 0, 1) template <class T> Vector3<T> Vector3<T>::up = Vector3<T>(0, 0, 1); // (0, 0, 0) template <class T> Vector3<T> Vector3<T>::zero = Vector3<T>(0, 0, 0); template <class T> T Vector3<T>::Dot(Vector3<T> lhs, Vector3<T> rhs) { return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z; } template <class T> Vector3<T> Vector3<T>::Cross(Vector3<T> lhs, Vector3<T> rhs) { double _x = lhs.y * rhs.z - rhs.y * lhs.z; double _y = lhs.z * rhs.x - rhs.z * lhs.x; double _z = lhs.x * rhs.y - rhs.x * lhs.y; return Vector3<T>(_x, _y, _z); } template <class T> T Vector3<T>::Distance(Vector3<T> a, Vector3<T> b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z)); } template <class T> Vector3<T> Vector3<T>::Normalize(Vector3<T> value) { if (value == zero) { return zero; } else { Vector3<T> tempVec = Vector3<T>(); tempVec.x = value.x / value.magnitude; tempVec.y = value.y / value.magnitude; tempVec.z = value.z / value.magnitude; return tempVec; } } template <class T> T Vector3<T>::Angle(Vector3<T> from, Vector3<T> to) { T cos = Dot(from.normalized(), to.normalized()); if (cos < -1) { cos = -1; } if (cos > 1) { cos = 1; } return acos(cos) * (180 / M_PI); } template <class T> T Vector3<T>::AngleBetween(Vector3<T> from, Vector3<T> to) { T cos = Dot(from.normalized(), to.normalized()); if (cos < -1) { cos = -1; } if (cos > 1) { cos = 1; } return acos(cos); } template <class T> Vector3<T> Vector3<T>::Max(Vector3<T> lhs, Vector3<T> rhs){ Vector3<T> temp = Vector3<T>(); temp.x = max(lhs.x, rhs.x); temp.y = max(lhs.y, rhs.y); temp.z = max(lhs.z, rhs.z); return temp; } template <class T> Vector3<T> Vector3<T>::Min(Vector3<T> lhs, Vector3<T> rhs) { Vector3<T> temp = Vector3<T>(); temp.x = min(lhs.x, rhs.x); temp.y = min(lhs.y, rhs.y); temp.z = min(lhs.z, rhs.z); return temp; } template <class T> Vector3<T> Vector3<T>::Project(Vector3<T> vector, Vector3<T> onNormal) { if (vector == zero || onNormal == zero) { return zero; } return Dot(vector, onNormal) / (onNormal.magnitude() * onNormal.magnitude()) * onNormal; } template <class T> Vector3<T> Vector3<T>::Scale(Vector3<T> a, Vector3<T> b) { Vector3<T> temp = Vector3<T>(); temp.x = a.x * b.x; temp.y = ay * by; temp.z = a.z * b.z; return temp; } template <class T> Vector3<T> Vector3<T>::normalized() { return Normalize(Vector3<T>(x, y, z)); } template <class T> void Vector3<T>::Scale(Vector3<T> scale) { x *= scale.x; y *= scale.y; z * = scale.z; } template <class T> void Vector3<T>::Set(T _x, T _y, T _z) { x = _x; y = _y; z = _z; } template <class T> string Vector3<T>::ToString() { stringstream ss; ss << "(" << x << "," << y << "," << z << ")"; return ss.str(); } template <class T> bool Vector3<T>::operator==(const Vector3<T> &rhs) const { if (this->x == rhs.x && this->y == rhs.y && this->z == rhs.z) { return true; } else { return false; } } template <class T> bool Vector3<T>::operator!=(const Vector3<T> &rhs) const { return !(this == rhs) } // operator overloading is not a class member --------------------------------------- template <class T> Vector3<T> operator+(const Vector3<T> &a, const Vector3<T> &b) { return Vector3<T>(a.x + b.x, a.y + b.y, a.z + b.z); } template <class T> Vector3<T> operator-(const Vector3<T> &a, const Vector3<T> &b) { return Vector3<T>(a.x - b.x, a.y - b.y, a.z - b.z); } template <class T> Vector3<T> operator*(const T d, const Vector3<T> &a) { return Vector3<T>(a.x * d, a.y * d, a.z * d); } template <class T> Vector3<T> operator*(const Vector3<T> &a, const T d ) { return Vector3<T>(a.x * d, a.y * d, a.z * d); } template <class T> Vector3<T> operator/(const Vector3<T> &a, const T d) { return Vector3<T>(a.x / d, a.y / d, a.z / d); } } #endif