随着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