序言
随着Unity技术的全球性大规模普及,其API的易用性得到了越来越多的开发者的青睐。
本篇在D子宇的工作基础上,仿照Unity的类结构,将其拓展转换为C++类模板。
以便在其它C++工程中更加方便使用。
源代码地址:https://github.com/duzixi/XYZ
博文首发:https://www.csdn.net/duzixi
源代码
Vector3.h
// // Vector3.h // XYZ // 三维空间常用类模板C++实现。封装了三维空间向量的常用成员与方法。 // // 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; // 构造函数 ============================== Vector3(); Vector3(T _x, T _y); Vector3(T _x, T _y, T _z); // 析构函数 ~Vector3(); // 属性==================================== // 常用向量 /* 本类采用坐标系如下: y ^ | | 俯视图 z轴垂直屏幕朝上 | 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; // 模的平方 T sqrMagnitude; // 模 T magnitude; // 类方法 =============================== // 点乘 static T Dot(Vector3<T> lhs, Vector3<T> rhs); // 叉乘 static Vector3<T> Cross(Vector3<T> lhs, Vector3<T> rhs); // 距离 static T Distance(Vector3<T> a, Vector3<T> b); // 单位化 static Vector3<T> Normalize(Vector3<T> value); // 夹角大小(角度) static T Angle(Vector3<T> from, Vector3<T> to); // 夹角大小(弧度) static T AngleBetween(Vector3<T> from, Vector3<T> to); // 最大值(X,Y,Z均取最大) static Vector3<T> Max(Vector3<T> lhs, Vector3<T> rhs); // 最小值(X,Y,Z均取最小) static Vector3<T> Min(Vector3<T> lhs, Vector3<T> rhs); // 向量投影 static Vector3<T> Project(Vector3<T> vector, Vector3<T> onNormal); // 缩放 static Vector3<T> Scale(Vector3<T> a, Vector3<T> b); // 成员方法 ============================== // 单位化(不改变向量本身) Vector3<T> normalized(); // 缩放 void Scale(Vector3<T> scale); // 设置 void Set(T _x, T _y, T _z); // 返回字符串 string ToString(); // 运算符重载 ========================== // 比较是否相等 bool operator==(const Vector3<T> &rhs) const; // 比较是否不相等 bool operator!=(const Vector3<T> &rhs) const; }; // 运算符重载 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++实现。封装了三维空间向量的常用成员与方法。 // // 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 = a.y * b.y; 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) } // 运算符重载并不是类成员 ---------------------------------------- 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