【C++】XYZ系列——Vector3类模板(仿Unity实现)

2019-04-13 22:13发布

序言

随着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 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 back; // (0, 0, -1) static Vector3 down; // (0, 1, 0) static Vector3 forward; // (0, 1, 0) static Vector3 fwd; // (-1, 0, 0) static Vector3 left; // (1, 1, 1) static Vector3 one; // (1, 0, 0) static Vector3 right; // (0, 0, 1) static Vector3 up; // (0, 0, 0) static Vector3 zero; // 模的平方 T sqrMagnitude; // 模 T magnitude; // 类方法 =============================== // 点乘 static T Dot(Vector3 lhs, Vector3 rhs); // 叉乘 static Vector3 Cross(Vector3 lhs, Vector3 rhs); // 距离 static T Distance(Vector3 a, Vector3 b); // 单位化 static Vector3 Normalize(Vector3 value); // 夹角大小(角度) static T Angle(Vector3 from, Vector3 to); // 夹角大小(弧度) static T AngleBetween(Vector3 from, Vector3 to); // 最大值(X,Y,Z均取最大) static Vector3 Max(Vector3 lhs, Vector3 rhs); // 最小值(X,Y,Z均取最小) static Vector3 Min(Vector3 lhs, Vector3 rhs); // 向量投影 static Vector3 Project(Vector3 vector, Vector3 onNormal); // 缩放 static Vector3 Scale(Vector3 a, Vector3 b); // 成员方法 ============================== // 单位化(不改变向量本身) Vector3 normalized(); // 缩放 void Scale(Vector3 scale); // 设置 void Set(T _x, T _y, T _z); // 返回字符串 string ToString(); // 运算符重载 ========================== // 比较是否相等 bool operator==(const Vector3 &rhs) const; // 比较是否不相等 bool operator!=(const Vector3 &rhs) const; }; // 运算符重载 template Vector3 operator+(const Vector3 &a, const Vector3 &b); template Vector3 operator-(const Vector3 &a, const Vector3 &b); template Vector3 operator*(const T d, const Vector3 &a); template Vector3 operator* (const Vector3 &a, const T d); template Vector3 operator/ (const Vector3 &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 Vector3::Vector3() { } template Vector3::~Vector3() { } template Vector3::Vector3(T _x, T _y) { x = _x; y = _y; z = 0; sqrMagnitude = x * x + y * y + z * z; magnitude = sqrt(sqrMagnitude); } template Vector3::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 Vector3 Vector3::back = Vector3(0, -1, 0); // (0, 0, -1) template Vector3 Vector3::down = Vector3(0, 0, -1); // (0, 1, 0) template Vector3 Vector3::forward = Vector3(0, 1, 0); // (0, 1, 0) template Vector3 Vector3::fwd = Vector3(0, 1, 0); // (-1, 0, 0) template Vector3 Vector3::left = Vector3(-1, 0, 0); // (1, 1, 1) template Vector3 Vector3::one = Vector3(1, 1, 1); // (1, 0, 0) template Vector3 Vector3::right = Vector3(1, 0, 0); // (0, 0, 1) template Vector3 Vector3::up = Vector3(0, 0, 1); // (0, 0, 0) template Vector3 Vector3::zero = Vector3(0, 0, 0); template T Vector3::Dot(Vector3 lhs, Vector3 rhs) { return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z; } template Vector3 Vector3::Cross(Vector3 lhs, Vector3 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(_x, _y, _z); } template T Vector3::Distance(Vector3 a, Vector3 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 Vector3 Vector3::Normalize(Vector3 value) { if (value == zero) { return zero; } else { Vector3 tempVec = Vector3(); tempVec.x = value.x / value.magnitude; tempVec.y = value.y / value.magnitude; tempVec.z = value.z / value.magnitude; return tempVec; } } template T Vector3::Angle(Vector3 from, Vector3 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 T Vector3::AngleBetween(Vector3 from, Vector3 to) { T cos = Dot(from.normalized(), to.normalized()); if (cos < -1) { cos = -1; } if (cos > 1) { cos = 1; } return acos(cos); } template Vector3 Vector3::Max(Vector3 lhs, Vector3 rhs){ Vector3 temp = Vector3(); temp.x = max(lhs.x, rhs.x); temp.y = max(lhs.y, rhs.y); temp.z = max(lhs.z, rhs.z); return temp; } template Vector3 Vector3::Min(Vector3 lhs, Vector3 rhs) { Vector3 temp = Vector3(); temp.x = min(lhs.x, rhs.x); temp.y = min(lhs.y, rhs.y); temp.z = min(lhs.z, rhs.z); return temp; } template Vector3 Vector3::Project(Vector3 vector, Vector3 onNormal) { if (vector == zero || onNormal == zero) { return zero; } return Dot(vector, onNormal) / (onNormal.magnitude() * onNormal.magnitude()) * onNormal; } template Vector3 Vector3::Scale(Vector3 a, Vector3 b) { Vector3 temp = Vector3(); temp.x = a.x * b.x; temp.y = a.y * b.y; temp.z = a.z * b.z; return temp; } template Vector3 Vector3::normalized() { return Normalize(Vector3(x, y, z)); } template void Vector3::Scale(Vector3 scale) { x *= scale.x; y *= scale.y; z *= scale.z; } template void Vector3::Set(T _x, T _y, T _z) { x = _x; y = _y; z = _z; } template string Vector3::ToString() { stringstream ss; ss << "(" << x << "," << y << "," << z << ")"; return ss.str(); } template bool Vector3::operator==(const Vector3 &rhs) const { if (this->x == rhs.x && this->y == rhs.y && this->z == rhs.z) { return true; } else { return false; } } template bool Vector3::operator!=(const Vector3 &rhs) const { return !(this == rhs) } // 运算符重载并不是类成员 ---------------------------------------- template Vector3 operator+(const Vector3 &a, const Vector3 &b) { return Vector3(a.x + b.x, a.y + b.y, a.z + b.z); } template Vector3 operator-(const Vector3 &a, const Vector3 &b) { return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); } template Vector3 operator*(const T d, const Vector3 &a) { return Vector3(a.x * d, a.y * d, a.z * d); } template Vector3 operator*(const Vector3 &a, const T d ) { return Vector3(a.x * d, a.y * d, a.z * d); } template Vector3 operator/(const Vector3 &a, const T d) { return Vector3(a.x / d, a.y / d, a.z / d); } } #endif