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

序言

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


猜你喜欢

转载自blog.csdn.net/lotusiki/article/details/79925626